public async Task Verify_that_person_can_be_Posted() { var cdpServicesDal = new CdpServicesDal(); var dtos = await cdpServicesDal.Open(this.credentials, this.cancelationTokenSource.Token); var siteDirectory = (CDP4Common.DTO.SiteDirectory)dtos.Single(x => x.ClassKind == ClassKind.SiteDirectory); var context = siteDirectory.Route; var operationContainer = new OperationContainer(context, siteDirectory.RevisionNumber); var person = new CDP4Common.DTO.Person(Guid.NewGuid(), 1); person.ShortName = Guid.NewGuid().ToString(); person.Surname = Guid.NewGuid().ToString(); person.GivenName = Guid.NewGuid().ToString(); person.AddContainer(ClassKind.SiteDirectory, siteDirectory.Iid); var operation1 = new Operation(null, person, OperationKind.Create); operationContainer.AddOperation(operation1); var siteDirectoryClone = siteDirectory.DeepClone <CDP4Common.DTO.SiteDirectory>(); siteDirectoryClone.Person.Add(person.Iid); var operation2 = new Operation(siteDirectory, siteDirectoryClone, OperationKind.Update); operationContainer.AddOperation(operation2); var result = await cdpServicesDal.Write(operationContainer); var resultPerson = (CDP4Common.DTO.Person)result.Single(x => x.Iid == person.Iid); Assert.NotNull(resultPerson); }
/// <summary>Write generated element definition</summary> /// <param name="elementDefinition">Element definition that will be written <see cref="ElementDefinition"/></param> /// <param name="originalIteration">Current iteration used for creating write transaction <see cref="Iteration"/></param> /// <param name="clonedIteration">Cloned iteration that will contain element definition <see cref="Iteration"/></param> /// <returns> /// The <see cref="Task"/> /// </returns> private async Task WriteElementDefinition(ElementDefinition elementDefinition, Iteration originalIteration, Iteration clonedIteration) { try { var transactionContext = TransactionContextResolver.ResolveContext(originalIteration); var operationContainer = new OperationContainer(transactionContext.ContextRoute()); operationContainer.AddOperation(new Operation(originalIteration.ToDto(), clonedIteration.ToDto(), OperationKind.Update)); foreach (var newThing in elementDefinition.QueryContainedThingsDeep()) { operationContainer.AddOperation(new Operation(null, newThing.ToDto(), OperationKind.Create)); } await this.configuration.Session.Dal.Write(operationContainer); this.NotifyMessage($"Successfully generated ElementDefinition {elementDefinition.Name} ({elementDefinition.ShortName}).", LogVerbosity.Info); } catch (Exception ex) { this.NotifyMessage($"Cannot generate ElementDefinition {elementDefinition.Name} ({elementDefinition.ShortName}). Exception: {ex.Message}", LogVerbosity.Error); } }
public void VerifyThatResolveRouteThrowsExceptionWhenOperationsAreForMultipleTopContainers() { var engineeringModelIid_1 = Guid.NewGuid(); var iterationIid_1 = Guid.NewGuid(); var iteration_1 = new Iteration(iterationIid_1, 1); iteration_1.AddContainer(ClassKind.EngineeringModel, engineeringModelIid_1); var topContainerContext = iteration_1.GetTopContainerRoute(); var operationContainer = new OperationContainer(topContainerContext, 1); var modifiedIteration_1 = new Iteration(iterationIid_1, 2); modifiedIteration_1.AddContainer(ClassKind.EngineeringModel, engineeringModelIid_1); var operation_1 = new Operation(iteration_1, modifiedIteration_1, OperationKind.Update); operationContainer.AddOperation(operation_1); var engineeringModelIid_2 = Guid.NewGuid(); var iterationIid_2 = Guid.NewGuid(); var iteration_2 = new Iteration(iterationIid_2, 1); iteration_2.AddContainer(ClassKind.EngineeringModel, engineeringModelIid_2); var modifiedIteration_2 = new Iteration(iterationIid_2, 2); modifiedIteration_2.AddContainer(ClassKind.EngineeringModel, engineeringModelIid_2); var operation_2 = new Operation(iteration_2, modifiedIteration_2, OperationKind.Update); Assert.Throws <ArgumentException>(() => operationContainer.AddOperation(operation_2)); }
public void VerifyThatModifyShiftCopyOperationsWorks2() { // all the things cannot be copied this.permissionService.Setup(x => x.CanWrite(It.Is <ClassKind>(cl => cl != ClassKind.ParameterSubscription), It.IsAny <Thing>())).Returns(true); this.session.Setup(x => x.OpenIterations).Returns( new Dictionary <Iteration, Tuple <DomainOfExpertise, Participant> > { { this.iteration1, new Tuple <DomainOfExpertise, Participant>(domain1, null) }, { this.iteration2, new Tuple <DomainOfExpertise, Participant>(domain2, null) } }); var iteration2Clone = this.iteration2.Clone(false); var defClone = this.rootDef.Clone(false); defClone.Iid = Guid.NewGuid(); iteration2Clone.Element.Add(defClone); var transactionContext = TransactionContextResolver.ResolveContext(this.iteration2); var context = transactionContext.ContextRoute(); var operationContainer = new OperationContainer(context, this.model2.RevisionNumber); operationContainer.AddOperation(new Operation(this.iteration2.ToDto(), iteration2Clone.ToDto(), OperationKind.Update)); operationContainer.AddOperation(new Operation(this.rootDef.ToDto(), defClone.ToDto(), OperationKind.Copy)); var copyHandler = new CopyOperationHandler(this.session.Object); copyHandler.ModifiedCopyOperation(operationContainer); var operations = operationContainer.Operations.ToList(); Assert.AreEqual(13, operations.Count); Assert.IsNotEmpty(operationContainer.Context); }
/// <summary> /// Method syncing the given <paramref name="selectedIids"/> from the source server to the target server /// </summary> /// <param name="selectedIids"> /// A list of thing iids to sync /// </param> /// <returns> /// The <see cref="Task"/> /// </returns> public override async Task Sync(IEnumerable <Guid> selectedIids) { var operationContainer = new OperationContainer(this.TargetSiteDirectory.Route); var cloneTargetSiteDirectory = this.TargetSiteDirectory.Clone(false); // sync SiteReferenceDataLibrary foreach (var sourceRdl in this.SourceSiteDirectory.SiteReferenceDataLibrary .Where(t => selectedIids.Contains(t.Iid)) .ToList()) { await this.SourceSession.Read(sourceRdl); var cloneSourceThing = sourceRdl.Clone(true); cloneSourceThing.Container = this.TargetSiteDirectory; var index = cloneTargetSiteDirectory.SiteReferenceDataLibrary .FindIndex(t => t.Iid == cloneSourceThing.Iid); if (index == -1) { cloneTargetSiteDirectory.SiteReferenceDataLibrary.Add(cloneSourceThing); } else { cloneTargetSiteDirectory.SiteReferenceDataLibrary[index] = cloneSourceThing; } var targetRdl = this.TargetSiteDirectory .SiteReferenceDataLibrary .FirstOrDefault(t => t.ShortName == sourceRdl.ShortName); if (targetRdl != null) { await this.TargetSession.Read(targetRdl); } var allTargetThings = targetRdl?.QueryContainedThingsDeep() .ToDictionary(thing => thing.Iid, thing => thing) ?? new Dictionary <Guid, Thing>(); foreach (var toBeMovedThing in cloneSourceThing.QueryContainedThingsDeep()) { operationContainer.AddOperation(this.GetOperation(toBeMovedThing, allTargetThings)); } } // update target SiteDirectory operationContainer.AddOperation(new Operation( this.TargetSiteDirectory.ToDto(), cloneTargetSiteDirectory.ToDto(), OperationKind.Update)); await this.TargetSession.Write(operationContainer); }
public void VerifyThatDryCopyDoesNotCopySubscriptionWithInactiveDomain() { this.permissionService.Setup(x => x.CanWrite(It.IsAny <ClassKind>(), It.IsAny <Thing>())).Returns(true); this.session.Setup(x => x.OpenIterations).Returns( new Dictionary <Iteration, Tuple <DomainOfExpertise, Participant> > { { this.iteration1, new Tuple <DomainOfExpertise, Participant>(domain1, null) }, { this.iteration2, new Tuple <DomainOfExpertise, Participant>(domain1, null) } }); this.subscription1.Owner = this.domain3; var iteration2Clone = this.iteration2.Clone(false); var defClone = this.rootDef.Clone(false); defClone.Iid = Guid.NewGuid(); iteration2Clone.Element.Add(defClone); var transactionContext = TransactionContextResolver.ResolveContext(this.iteration2); var context = transactionContext.ContextRoute(); var operationContainer = new OperationContainer(context, this.model2.RevisionNumber); operationContainer.AddOperation(new Operation(this.iteration2.ToDto(), iteration2Clone.ToDto(), OperationKind.Update)); operationContainer.AddOperation(new Operation(this.rootDef.ToDto(), defClone.ToDto(), OperationKind.CopyDefaultValuesChangeOwner)); var copyHandler = new CopyOperationHandler(this.session.Object); copyHandler.ModifiedCopyOperation(operationContainer); var operations = operationContainer.Operations.ToList(); Assert.AreEqual(13, operations.Count); Assert.IsNotEmpty(operationContainer.Context); // check that operation container is correctly built var ownedThings = operationContainer.Operations.Select(x => x.ModifiedThing) .Where(x => x.ClassKind != ClassKind.ParameterSubscription) .OfType <Dto.IOwnedThing>() .ToList(); var dtoOwner = ownedThings.Select(x => x.Owner).Distinct().Single(); Assert.AreEqual(dtoOwner, this.domain1.Iid); var subCount = operationContainer.Operations.Select(x => x.ModifiedThing) .OfType <Dto.ParameterSubscription>().Count(); Assert.AreEqual(0, subCount); }
/// <summary> /// Modify the <see cref="OperationContainer"/> to compensate for operations /// that should be performed by the data-source but is not by the WSP. /// </summary> /// <param name="operationContainer">The <see cref="OperationContainer"/> to modify</param> public void ModifyOperationContainer(OperationContainer operationContainer) { var operationsToAdd = new List <Operation>(); foreach (var operation in operationContainer.Operations) { if (operation.OperationKind == OperationKind.Create) { var parameterOverride = operation.ModifiedThing as ParameterOverride; if (parameterOverride != null) { operationsToAdd.AddRange(this.AddParameterSubscriptionCreateOperation(operationContainer, parameterOverride)); } } else if (operation.OperationKind == OperationKind.Update) { var possibleStateList = operation.ModifiedThing as PossibleFiniteStateList; if (possibleStateList != null) { operationsToAdd.AddRange(this.ModifyActualStateKindOnDefaultPossibleStateUpdate(possibleStateList)); } } } foreach (var operation in operationsToAdd) { operationContainer.AddOperation(operation); } }
/// <summary> /// Computes a <see cref="OperationContainer"/> that contains update operations on value-sets /// </summary> /// <param name="context"> /// The route of the <see cref="CDP4Common.DTO.SiteDirectory"/> or <see cref="Iteration"/> for which the current <see cref="OperationContainer"/> is valid. /// </param> /// <param name="dtos">The returned <see cref="Dto.Thing"/>s</param> /// <param name="copyThingMap">The copy map containing the original <see cref="Thing"/> associated to their copy</param> /// <returns>The <see cref="OperationContainer"/></returns> public OperationContainer CreateValueSetsUpdateOperations(string context, IEnumerable <Dto.Thing> dtos, IReadOnlyDictionary <Thing, Thing> copyThingMap) { var dtolist = dtos.ToList(); var topContainer = dtolist.SingleOrDefault(x => x is Dto.TopContainer); if (topContainer == null) { throw new InvalidOperationException("No Top container were found in the returned list of dtos."); } // Gets the parameter base which value set shall be updated var copyParameterBases = dtolist.OfType <Dto.ParameterBase>().ToList(); var copyParameterBasesIds = copyParameterBases.Select(p => p.Iid).ToList(); var valuesets = dtolist.Where(dto => dto.ClassKind == ClassKind.ParameterValueSet || dto.ClassKind == ClassKind.ParameterSubscriptionValueSet || dto.ClassKind == ClassKind.ParameterOverrideValueSet).ToList(); this.ComputeRoutes(valuesets, dtolist); var valueSetsClones = valuesets.Select(dto => dto.DeepClone <Dto.Thing>()).ToList(); // The original of the copy are normally in the map var originalParameterBases = copyThingMap.Where(x => copyParameterBasesIds.Contains(x.Value.Iid)).ToList(); // set the values foreach (var copyPair in originalParameterBases) { var copyId = copyPair.Value.Iid; var originalParameter = (ParameterBase)copyPair.Key; var copyDto = copyParameterBases.Single(x => x.Iid == copyId); // value sets to update var copyValueSets = valueSetsClones.Where(x => copyDto.ValueSets.Contains(x.Iid)).ToList(); var defaultValueSet = this.GetDefaultValueSet(originalParameter); if (defaultValueSet == null) { continue; } this.SetValueSetValues(copyValueSets, defaultValueSet); } var operationContainer = new OperationContainer(context, topContainer.RevisionNumber); foreach (var valueSetsClone in valueSetsClones) { var valuesetToUpdate = valuesets.Single(x => x.Iid == valueSetsClone.Iid); var operation = new Operation(valuesetToUpdate, valueSetsClone, OperationKind.Update); operationContainer.AddOperation(operation); } return(operationContainer); }
/// <summary> /// Modify the <see cref="OperationContainer"/> if it contains copy <see cref="Operation"/> /// </summary> /// <param name="operationContainer">The <see cref="OperationContainer"/> to modify</param> public void ModifiedCopyOperation(OperationContainer operationContainer) { var operationsToAdd = new List <Operation>(); var copyOperationCount = operationContainer.Operations.Count(x => x.OperationKind.IsCopyOperation()); if (copyOperationCount > 1) { // TODO: support this if needed throw new NotSupportedException("Only one copy operation per transaction is supported."); } var copyOperation = operationContainer.Operations.SingleOrDefault(x => x.OperationKind.IsCopyOperation()); if (copyOperation == null) { return; } this.ComputeOperations(copyOperation); operationsToAdd.AddRange(this.operations); foreach (var operation in operationsToAdd) { operationContainer.AddOperation(operation); } // remove the copy operations operationContainer.RemoveOperation(copyOperation); // update the update iteration operation var iterationOperation = operationContainer.Operations.Single(x => x.OperationKind == OperationKind.Update); var updatedIteration = iterationOperation.ModifiedThing.QuerySourceThing(); var originalIteration = iterationOperation.OriginalThing.QuerySourceThing(); operationContainer.RemoveOperation(iterationOperation); operationContainer.AddOperation(new Operation(originalIteration.ToDto(), updatedIteration.ToDto(), OperationKind.Update)); }
public async Task Verify_that_person_can_be_Posted() { var uri = new Uri("http://ocdt-dev.rheagroup.com"); var credentials = new Credentials("admin", "pass", uri); var wspdal = new WspDal(); var dtos = await wspdal.Open(credentials, this.cancelationTokenSource.Token); var siteDirectory = (CDP4Common.DTO.SiteDirectory)dtos.Single(x => x.ClassKind == ClassKind.SiteDirectory); var context = siteDirectory.Route; var operationContainer = new OperationContainer(context, siteDirectory.RevisionNumber); var person = new CDP4Common.DTO.Person(Guid.NewGuid(), 1); person.ShortName = Guid.NewGuid().ToString(); person.Surname = Guid.NewGuid().ToString(); person.GivenName = Guid.NewGuid().ToString(); person.AddContainer(ClassKind.SiteDirectory, Guid.Parse("eb77f3e1-a0f3-412d-8ed6-b8ce881c0145")); var operation1 = new Operation(null, person, OperationKind.Create); operationContainer.AddOperation(operation1); var siteDirectoryClone = siteDirectory.DeepClone <CDP4Common.DTO.SiteDirectory>(); siteDirectoryClone.Person.Add(person.Iid); var operation2 = new Operation(siteDirectory, siteDirectoryClone, OperationKind.Update); operationContainer.AddOperation(operation2); var result = await wspdal.Write(operationContainer); var resultPerson = (CDP4Common.DTO.Person)result.Single(x => x.Iid == person.Iid); Assert.NotNull(resultPerson); }
public void VerifyExecutionOfOperationAddAndRemove() { var elementDefinition = new ElementDefinition(Guid.NewGuid(), 0); elementDefinition.PartialRoutes.Add("iteration/b58ea73d-350d-4520-b9d9-a52c75ac2b5d"); elementDefinition.PartialRoutes.Add("EngineeringModel/5e5dc7f8-833d-4331-b421-eb2c64fcf64b"); var clone = elementDefinition.DeepClone <ElementDefinition>(); var operation = new Operation(elementDefinition, clone, OperationKind.Update); var operationContainer = new OperationContainer(this.iterationContext); operationContainer.AddOperation(operation); Assert.AreEqual(1, operationContainer.Operations.Count()); operationContainer.RemoveOperation(operation); Assert.AreEqual(0, operationContainer.Operations.Count()); }
/// <summary> /// Executes the Ok Command /// </summary> private async void ExecuteOk() { this.IsBusy = true; this.LoadingMessage = "Exporting..."; try { var creds = new Credentials(this.selectedSession.Credentials.UserName, this.Password, new Uri(this.Path)); // TODO: change this to allow (file) dal selection for export var dal = this.dals.Single(x => x.Metadata.DalType == DalType.File); var dalInstance = (IDal)Activator.CreateInstance(dal.Value.GetType()); var fileExportSession = new Session(dalInstance, creds); // create write var operationContainers = new List <OperationContainer>(); // TODO: allow iteration setup selection by user var openIterations = this.selectedSession.OpenIterations.Select(x => x.Key); foreach (var iteration in openIterations) { var transactionContext = TransactionContextResolver.ResolveContext(iteration); var operationContainer = new OperationContainer(transactionContext.ContextRoute()); var dto = iteration.ToDto(); var operation = new Operation(null, dto, OperationKind.Create); operationContainer.AddOperation(operation); operationContainers.Add(operationContainer); } var result = await dalInstance.Write(operationContainers); this.DialogResult = new BaseDialogResult(true); } catch (Exception ex) { this.ErrorMessage = ex.Message; } finally { this.IsBusy = false; } }
/// <summary> /// Modify the <see cref="OperationContainer"/> to compensate for operations /// that should be performed by the data-source but is not by the WSP. /// </summary> /// <param name="operationContainer">The <see cref="OperationContainer"/> to modify</param> public void ModifyOperationContainer(OperationContainer operationContainer) { var operationsToAdd = new List <Operation>(); foreach (var operation in operationContainer.Operations) { if (operation.OperationKind == OperationKind.Update) { var possibleStateList = operation.ModifiedThing as PossibleFiniteStateList; if (possibleStateList != null) { operationsToAdd.AddRange(this.ModifyActualStateKindOnDefaultPossibleStateUpdate(possibleStateList)); } } } foreach (var operation in operationsToAdd) { operationContainer.AddOperation(operation); } }
public void Verify_that_serialization_of_Post_Operation_returns_expected_result() { var expected = @"{""_delete"":[],""_create"":[{""category"":[],""classKind"":""File"",""excludedDomain"":[],""excludedPerson"":[],""fileRevision"":[""cb54801a-9a08-495f-996c-6467a86ed9cc""],""iid"":""643e6154-a035-4445-a4f2-2c7ff5d2fdbd"",""lockedBy"":null,""modifiedOn"":""0001-01-01T00:00:00.000Z"",""owner"":""0e92edde-fdff-41db-9b1d-f2e484f12535"",""revisionNumber"":0},{""classKind"":""FileRevision"",""containingFolder"":null,""contentHash"":""F73747371CFD9473C19A0A7F99BCAB008474C4CA"",""createdOn"":""0001-01-01T00:00:00.000Z"",""creator"":""284334dd-e8e5-42d6-bc8a-715c507a7f02"",""excludedDomain"":[],""excludedPerson"":[],""fileType"":[{""k"":1,""v"":""b16894e4-acb5-4e81-a118-16c00eb86d8f""}],""iid"":""cb54801a-9a08-495f-996c-6467a86ed9cc"",""modifiedOn"":""0001-01-01T00:00:00.000Z"",""name"":""testfile"",""revisionNumber"":0}],""_update"":[{""classKind"":""DomainFileStore"",""iid"":""da7dddaa-02aa-4897-9935-e8d66c811a96"",""file"":[""643e6154-a035-4445-a4f2-2c7ff5d2fdbd""]}]}"; var engineeringModelIid = Guid.Parse("9ec982e4-ef72-4953-aa85-b158a95d8d56"); var iterationIid = Guid.Parse("e163c5ad-f32b-4387-b805-f4b34600bc2c"); var domainFileStoreIid = Guid.Parse("da7dddaa-02aa-4897-9935-e8d66c811a96"); var fileIid = Guid.Parse("643e6154-a035-4445-a4f2-2c7ff5d2fdbd"); var fileRevisionIid = Guid.Parse("cb54801a-9a08-495f-996c-6467a86ed9cc"); var domainOfExpertiseIid = Guid.Parse("0e92edde-fdff-41db-9b1d-f2e484f12535"); var fileTypeIid = Guid.Parse("b16894e4-acb5-4e81-a118-16c00eb86d8f"); var participantIid = Guid.Parse("284334dd-e8e5-42d6-bc8a-715c507a7f02"); var originalDomainFileStore = new DomainFileStore(domainFileStoreIid, 0); originalDomainFileStore.AddContainer(ClassKind.Iteration, iterationIid); originalDomainFileStore.AddContainer(ClassKind.EngineeringModel, engineeringModelIid); var modifiedDomainFileStore = originalDomainFileStore.DeepClone <DomainFileStore>(); modifiedDomainFileStore.File.Add(fileIid); var file = new CDP4Common.DTO.File(fileIid, 0); file.Owner = domainOfExpertiseIid; file.FileRevision.Add(fileRevisionIid); file.AddContainer(ClassKind.DomainFileStore, domainFileStoreIid); file.AddContainer(ClassKind.Iteration, iterationIid); file.AddContainer(ClassKind.EngineeringModel, engineeringModelIid); var fileRevision = new FileRevision(fileRevisionIid, 0); fileRevision.Name = "testfile"; fileRevision.ContentHash = "F73747371CFD9473C19A0A7F99BCAB008474C4CA"; fileRevision.FileType.Add(new OrderedItem() { K = 1, V = fileTypeIid }); fileRevision.Creator = participantIid; fileRevision.AddContainer(ClassKind.File, fileIid); fileRevision.AddContainer(ClassKind.DomainFileStore, domainFileStoreIid); fileRevision.AddContainer(ClassKind.Iteration, iterationIid); fileRevision.AddContainer(ClassKind.EngineeringModel, engineeringModelIid); var context = $"/EngineeringModel/{engineeringModelIid}/iteration/{iterationIid}"; var operationContainer = new OperationContainer(context, null); var updateCommonFileStoreOperation = new Operation(originalDomainFileStore, modifiedDomainFileStore, OperationKind.Update); operationContainer.AddOperation(updateCommonFileStoreOperation); var createFileOperation = new Operation(null, file, OperationKind.Create); operationContainer.AddOperation(createFileOperation); var createFileRevisionOperation = new Operation(null, fileRevision, OperationKind.Create); operationContainer.AddOperation(createFileRevisionOperation); var postOperation = new WspPostOperation(new MetaDataProvider()); foreach (var operation in operationContainer.Operations) { postOperation.ConstructFromOperation(operation); } using (var stream = new MemoryStream()) using (var streamReader = new StreamReader(stream)) { this.serializer.SerializeToStream(postOperation, stream); stream.Position = 0; Assert.AreEqual(expected, streamReader.ReadToEnd()); } }
public async Task VerifyThatFileCanBeUploaded() { this.dal = new WspDal { Session = this.session }; var filename = @"TestData\testfile.pdf"; var directory = TestContext.CurrentContext.TestDirectory; var filepath = Path.Combine(directory, filename); var files = new List <string> { filepath }; var contentHash = "F73747371CFD9473C19A0A7F99BCAB008474C4CA"; var uri = new Uri("https://cdp4services-test.cdp4.org"); this.credentials = new Credentials("admin", "pass", uri); var returned = await this.dal.Open(this.credentials, this.cancelationTokenSource.Token); var engineeringModeliid = Guid.Parse("9ec982e4-ef72-4953-aa85-b158a95d8d56"); var iterationiid = Guid.Parse("e163c5ad-f32b-4387-b805-f4b34600bc2c"); var domainFileStoreIid = Guid.Parse("da7dddaa-02aa-4897-9935-e8d66c811a96"); var fileIid = Guid.NewGuid(); var fileRevisionIid = Guid.NewGuid(); var domainOfExpertiseIid = Guid.Parse("0e92edde-fdff-41db-9b1d-f2e484f12535"); var fileTypeIid = Guid.Parse("b16894e4-acb5-4e81-a118-16c00eb86d8f"); //PDF var participantIid = Guid.Parse("284334dd-e8e5-42d6-bc8a-715c507a7f02"); var originalDomainFileStore = new CDP4Common.DTO.DomainFileStore(domainFileStoreIid, 0); originalDomainFileStore.AddContainer(ClassKind.Iteration, iterationiid); originalDomainFileStore.AddContainer(ClassKind.EngineeringModel, engineeringModeliid); var modifiedDomainFileStore = new CDP4Common.DTO.DomainFileStore(domainFileStoreIid, 0); modifiedDomainFileStore.File.Add(fileIid); modifiedDomainFileStore.AddContainer(ClassKind.Iteration, iterationiid); modifiedDomainFileStore.AddContainer(ClassKind.EngineeringModel, engineeringModeliid); var file = new CDP4Common.DTO.File(fileIid, 0) { Owner = domainOfExpertiseIid }; file.FileRevision.Add(fileRevisionIid); file.AddContainer(ClassKind.DomainFileStore, domainFileStoreIid); file.AddContainer(ClassKind.Iteration, iterationiid); file.AddContainer(ClassKind.EngineeringModel, engineeringModeliid); var fileRevision = new CDP4Common.DTO.FileRevision(fileRevisionIid, 0); fileRevision.Name = "testfile"; fileRevision.ContentHash = contentHash; fileRevision.FileType.Add(new OrderedItem() { K = 1, V = fileTypeIid }); fileRevision.Creator = participantIid; fileRevision.AddContainer(ClassKind.File, fileIid); fileRevision.AddContainer(ClassKind.DomainFileStore, domainFileStoreIid); fileRevision.AddContainer(ClassKind.Iteration, iterationiid); fileRevision.AddContainer(ClassKind.EngineeringModel, engineeringModeliid); var context = $"/EngineeringModel/{engineeringModeliid}/iteration/{iterationiid}"; var operationContainer = new OperationContainer(context); var updateCommonFileStoreOperation = new Operation(originalDomainFileStore, modifiedDomainFileStore, OperationKind.Update); operationContainer.AddOperation(updateCommonFileStoreOperation); var createFileOperation = new Operation(null, file, OperationKind.Create); operationContainer.AddOperation(createFileOperation); var createFileRevisionOperation = new Operation(null, fileRevision, OperationKind.Create); operationContainer.AddOperation(createFileRevisionOperation); Assert.DoesNotThrowAsync(async() => await dal.Write(operationContainer, files)); }
public void VerifyThatWSPPostBodyIsCorrectlyResolves() { var siteDirecortoryIid = Guid.Parse("f289023d-41e8-4aaf-aae5-1be1ecf24bac"); var domainOfExpertiseIid = Guid.NewGuid(); var context = "/SiteDirectory/f289023d-41e8-4aaf-aae5-1be1ecf24bac"; var operationContainer = new OperationContainer(context); var testDtoOriginal = new CDP4Common.DTO.Alias(iid: Guid.NewGuid(), rev: 1) { Content = "content", IsSynonym = false, LanguageCode = "en", }; testDtoOriginal.AddContainer(ClassKind.DomainOfExpertise, domainOfExpertiseIid); testDtoOriginal.AddContainer(ClassKind.SiteDirectory, siteDirecortoryIid); var testDtoModified = new CDP4Common.DTO.Alias(iid: testDtoOriginal.Iid, rev: 1) { Content = "content2", IsSynonym = true, LanguageCode = "en", }; testDtoModified.AddContainer(ClassKind.DomainOfExpertise, domainOfExpertiseIid); testDtoModified.AddContainer(ClassKind.SiteDirectory, siteDirecortoryIid); var testDtoOriginal2 = new CDP4Common.DTO.Definition(iid: Guid.NewGuid(), rev: 1) { Content = "somecontent", LanguageCode = "en", }; testDtoOriginal2.AddContainer(ClassKind.DomainOfExpertise, domainOfExpertiseIid); testDtoOriginal2.AddContainer(ClassKind.SiteDirectory, siteDirecortoryIid); var testDtoModified2 = new CDP4Common.DTO.Definition(iid: testDtoOriginal2.Iid, rev: 1) { Content = "somecontent2", LanguageCode = "en", }; testDtoModified2.AddContainer(ClassKind.DomainOfExpertise, domainOfExpertiseIid); testDtoModified2.AddContainer(ClassKind.SiteDirectory, siteDirecortoryIid); testDtoModified2.Citation.Add(Guid.NewGuid()); testDtoModified2.Citation.Add(Guid.NewGuid()); testDtoModified2.Citation.Add(Guid.NewGuid()); testDtoModified2.Citation.Add(Guid.NewGuid()); testDtoOriginal2.Citation.Add(testDtoModified2.Citation[0]); testDtoOriginal2.Citation.Add(testDtoModified2.Citation[1]); testDtoOriginal2.Citation.Add(testDtoModified2.Citation[2]); testDtoModified2.Citation.Remove(testDtoModified2.Citation[1]); testDtoOriginal2.Note.Add(new OrderedItem() { K = 1234, V = Guid.NewGuid() }); testDtoOriginal2.Note.Add(new OrderedItem() { K = 2345, V = Guid.NewGuid() }); testDtoModified2.Note.Add(new OrderedItem() { K = 234, V = Guid.NewGuid() }); testDtoModified2.Note.Add(new OrderedItem() { K = 2346, V = testDtoOriginal2.Note[1].V }); // make a few operations var operation1 = new Operation(null, testDtoModified, OperationKind.Create); var operation2 = new Operation(null, testDtoModified, OperationKind.Delete); var operation3 = new Operation(testDtoOriginal, testDtoModified, OperationKind.Update); var operation4 = new Operation(testDtoOriginal2, testDtoModified2, OperationKind.Update); operationContainer.AddOperation(operation1); operationContainer.AddOperation(operation2); operationContainer.AddOperation(operation3); operationContainer.AddOperation(operation4); var stream = new MemoryStream(); this.dal.ConstructPostRequestBodyStream(string.Empty, operationContainer, stream); Assert.AreNotEqual(0, stream.Length); }
public void VerifyThatCreatingOverrideCreateSubscriptions() { var domain1 = new CDP4Common.SiteDirectoryData.DomainOfExpertise(Guid.NewGuid(), this.assembler.Cache, this.uri); var domain2 = new CDP4Common.SiteDirectoryData.DomainOfExpertise(Guid.NewGuid(), this.assembler.Cache, this.uri); var model = new EngineeringModel(Guid.NewGuid(), this.assembler.Cache, this.uri); var iteration = new Iteration(Guid.NewGuid(), this.assembler.Cache, this.uri); var elementDef = new ElementDefinition(Guid.NewGuid(), this.assembler.Cache, this.uri) { Owner = domain1 }; var defForUsage = new ElementDefinition(Guid.NewGuid(), this.assembler.Cache, this.uri) { Owner = domain1 }; var usage = new ElementUsage(Guid.NewGuid(), this.assembler.Cache, this.uri) { ElementDefinition = defForUsage }; var parameter = new Parameter(Guid.NewGuid(), this.assembler.Cache, this.uri) { Owner = domain1 }; var parameterSubscription = new ParameterSubscription(Guid.NewGuid(), this.assembler.Cache, this.uri) { Owner = domain2 }; parameter.ParameterSubscription.Add(parameterSubscription); this.assembler.Cache.TryAdd(new CacheKey(parameter.Iid, iteration.Iid), new Lazy <Thing>(() => parameter)); this.assembler.Cache.TryAdd(new CacheKey(parameterSubscription.Iid, iteration.Iid), new Lazy <Thing>(() => parameterSubscription)); this.assembler.Cache.TryAdd(new CacheKey(usage.Iid, iteration.Iid), new Lazy <Thing>(() => usage)); var parameterOverride = new ParameterOverride(Guid.NewGuid(), this.assembler.Cache, this.uri) { Owner = domain1, Parameter = parameter }; usage.ParameterOverride.Add(parameterOverride); model.Iteration.Add(iteration); iteration.Element.Add(elementDef); iteration.Element.Add(defForUsage); elementDef.ContainedElement.Add(usage); defForUsage.Parameter.Add(parameter); var transactionContext = TransactionContextResolver.ResolveContext(iteration); var context = transactionContext.ContextRoute(); var operationContainer = new OperationContainer(context, model.RevisionNumber); operationContainer.AddOperation(new Operation(null, parameterOverride.ToDto(), OperationKind.Create)); operationContainer.AddOperation(new Operation(usage.ToDto(), usage.ToDto(), OperationKind.Update)); var modifier = new OperationModifier(this.session.Object); modifier.ModifyOperationContainer(operationContainer); Assert.AreEqual(3, operationContainer.Operations.Count()); }
public void VerifyThatActualFiniteStateKindIsUpdatedOnNewDefault() { var model = new EngineeringModel(Guid.NewGuid(), this.assembler.Cache, this.uri); var iteration = new Iteration(Guid.NewGuid(), this.assembler.Cache, this.uri); var possibleList1 = new PossibleFiniteStateList(Guid.NewGuid(), this.assembler.Cache, this.uri); var possibleList2 = new PossibleFiniteStateList(Guid.NewGuid(), this.assembler.Cache, this.uri); var possibleList3 = new PossibleFiniteStateList(Guid.NewGuid(), this.assembler.Cache, this.uri); var ps11 = new PossibleFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); var ps12 = new PossibleFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); var ps21 = new PossibleFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); var ps22 = new PossibleFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); var ps31 = new PossibleFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); var ps32 = new PossibleFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); possibleList1.PossibleState.Add(ps11); possibleList1.PossibleState.Add(ps12); possibleList2.PossibleState.Add(ps21); possibleList2.PossibleState.Add(ps22); possibleList3.PossibleState.Add(ps31); possibleList3.PossibleState.Add(ps32); var actualList1 = new ActualFiniteStateList(Guid.NewGuid(), this.assembler.Cache, this.uri); var actualList2 = new ActualFiniteStateList(Guid.NewGuid(), this.assembler.Cache, this.uri); actualList1.PossibleFiniteStateList.Add(possibleList1); actualList1.PossibleFiniteStateList.Add(possibleList2); var as11 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as11.PossibleState.Add(ps11); as11.PossibleState.Add(ps21); var as12 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as12.PossibleState.Add(ps11); as12.PossibleState.Add(ps22); var as13 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as13.PossibleState.Add(ps12); as13.PossibleState.Add(ps21); var as14 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as14.PossibleState.Add(ps12); as14.PossibleState.Add(ps22); actualList1.ActualState.Add(as11); actualList1.ActualState.Add(as12); actualList1.ActualState.Add(as13); actualList1.ActualState.Add(as14); actualList2.PossibleFiniteStateList.Add(possibleList2); actualList2.PossibleFiniteStateList.Add(possibleList3); var as21 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as21.PossibleState.Add(ps21); as21.PossibleState.Add(ps31); var as22 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as22.PossibleState.Add(ps21); as22.PossibleState.Add(ps32); var as23 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as23.PossibleState.Add(ps22); as23.PossibleState.Add(ps31); var as24 = new ActualFiniteState(Guid.NewGuid(), this.assembler.Cache, this.uri); as24.PossibleState.Add(ps22); as24.PossibleState.Add(ps32); actualList2.ActualState.Add(as21); actualList2.ActualState.Add(as22); actualList2.ActualState.Add(as23); actualList2.ActualState.Add(as24); model.Iteration.Add(iteration); iteration.PossibleFiniteStateList.Add(possibleList1); iteration.PossibleFiniteStateList.Add(possibleList2); iteration.PossibleFiniteStateList.Add(possibleList3); iteration.ActualFiniteStateList.Add(actualList1); iteration.ActualFiniteStateList.Add(actualList2); this.assembler.Cache.TryAdd(new CacheKey(model.Iid, null), new Lazy <Thing>(() => model)); this.assembler.Cache.TryAdd(new CacheKey(iteration.Iid, null), new Lazy <Thing>(() => iteration)); this.assembler.Cache.TryAdd(new CacheKey(possibleList1.Iid, iteration.Iid), new Lazy <Thing>(() => possibleList1)); this.assembler.Cache.TryAdd(new CacheKey(possibleList2.Iid, iteration.Iid), new Lazy <Thing>(() => possibleList2)); this.assembler.Cache.TryAdd(new CacheKey(possibleList3.Iid, iteration.Iid), new Lazy <Thing>(() => possibleList3)); this.assembler.Cache.TryAdd(new CacheKey(ps11.Iid, iteration.Iid), new Lazy <Thing>(() => ps11)); this.assembler.Cache.TryAdd(new CacheKey(ps12.Iid, iteration.Iid), new Lazy <Thing>(() => ps12)); this.assembler.Cache.TryAdd(new CacheKey(ps21.Iid, iteration.Iid), new Lazy <Thing>(() => ps21)); this.assembler.Cache.TryAdd(new CacheKey(ps22.Iid, iteration.Iid), new Lazy <Thing>(() => ps22)); this.assembler.Cache.TryAdd(new CacheKey(ps31.Iid, iteration.Iid), new Lazy <Thing>(() => ps31)); this.assembler.Cache.TryAdd(new CacheKey(ps32.Iid, iteration.Iid), new Lazy <Thing>(() => ps32)); this.assembler.Cache.TryAdd(new CacheKey(actualList1.Iid, iteration.Iid), new Lazy <Thing>(() => actualList1)); this.assembler.Cache.TryAdd(new CacheKey(actualList2.Iid, iteration.Iid), new Lazy <Thing>(() => actualList2)); this.assembler.Cache.TryAdd(new CacheKey(as11.Iid, iteration.Iid), new Lazy <Thing>(() => as11)); this.assembler.Cache.TryAdd(new CacheKey(as12.Iid, iteration.Iid), new Lazy <Thing>(() => as12)); this.assembler.Cache.TryAdd(new CacheKey(as13.Iid, iteration.Iid), new Lazy <Thing>(() => as13)); this.assembler.Cache.TryAdd(new CacheKey(as14.Iid, iteration.Iid), new Lazy <Thing>(() => as14)); this.assembler.Cache.TryAdd(new CacheKey(as21.Iid, iteration.Iid), new Lazy <Thing>(() => as21)); this.assembler.Cache.TryAdd(new CacheKey(as22.Iid, iteration.Iid), new Lazy <Thing>(() => as22)); this.assembler.Cache.TryAdd(new CacheKey(as23.Iid, iteration.Iid), new Lazy <Thing>(() => as23)); this.assembler.Cache.TryAdd(new CacheKey(as24.Iid, iteration.Iid), new Lazy <Thing>(() => as24)); possibleList1.DefaultState = ps11; as11.Kind = ActualFiniteStateKind.FORBIDDEN; var transactionContext = TransactionContextResolver.ResolveContext(iteration); var context = transactionContext.ContextRoute(); var operationContainer = new OperationContainer(context, model.RevisionNumber); var original = possibleList2.ToDto(); var modify = (CDP4Common.DTO.PossibleFiniteStateList)possibleList2.ToDto(); modify.DefaultState = ps21.Iid; operationContainer.AddOperation(new Operation(original, modify, OperationKind.Update)); Assert.AreEqual(1, operationContainer.Operations.Count()); var modifier = new OperationModifier(this.session.Object); modifier.ModifyOperationContainer(operationContainer); Assert.AreEqual(2, operationContainer.Operations.Count()); var addedOperation = operationContainer.Operations.Last(); var originalActualState = (CDP4Common.DTO.ActualFiniteState)addedOperation.OriginalThing; var modifiedActualState = (CDP4Common.DTO.ActualFiniteState)addedOperation.ModifiedThing; Assert.AreEqual(as11.Iid, originalActualState.Iid); Assert.AreEqual(ActualFiniteStateKind.MANDATORY, modifiedActualState.Kind); Assert.AreEqual(ActualFiniteStateKind.FORBIDDEN, originalActualState.Kind); }
public async Task VerifyWriteEnumerableOperationContainer() { var cache = new ConcurrentDictionary <CacheKey, Lazy <Thing> >(); var files = new[] { "file1" }; Assert.Throws <ArgumentNullException>(() => this.dal.Write((IEnumerable <OperationContainer>)null, files)); Assert.Throws <ArgumentException>(() => this.dal.Write(new List <OperationContainer>(), files)); var operationContainers = new[] { new OperationContainer("/SiteDirectory/00000000-0000-0000-0000-000000000000", 0) }; Assert.Throws <ArgumentException>(() => this.dal.Write(operationContainers, files)); var domainSys = new DomainOfExpertise(Guid.NewGuid(), cache, this.credentials.Uri) { ShortName = "SYS" }; this.siteDirectoryData.Domain.Add(domainSys); var domainAer = new DomainOfExpertise(Guid.NewGuid(), cache, this.credentials.Uri) { ShortName = "AER" }; this.siteDirectoryData.Domain.Add(domainAer); var domainProp = new DomainOfExpertise(Guid.NewGuid(), cache, this.credentials.Uri) { ShortName = "PROP" }; this.siteDirectoryData.Domain.Add(domainProp); // PersonRole var role = new PersonRole(Guid.NewGuid(), null, null); this.siteDirectoryData.PersonRole.Add(role); this.siteDirectoryData.DefaultPersonRole = role; // ParticipantRole var participantRole = new ParticipantRole(Guid.Empty, null, null); this.siteDirectoryData.ParticipantRole.Add(participantRole); this.siteDirectoryData.DefaultParticipantRole = participantRole; // Organization var organization = new Organization(Guid.NewGuid(), null, null) { Container = this.siteDirectoryData }; var sitedirectoryDto = (CDP4Common.DTO.SiteDirectory) this.siteDirectoryData.ToDto(); var clone = sitedirectoryDto.DeepClone <CDP4Common.DTO.SiteDirectory>(); var operation = new Operation(sitedirectoryDto, clone, OperationKind.Update); Assert.AreEqual(0, operationContainers.Single().Operations.Count()); operationContainers.Single().AddOperation(operation); Assert.AreEqual(1, operationContainers.Single().Operations.Count()); Assert.Throws <ArgumentException>(() => this.dal.Write(operationContainers, files)); operationContainers.Single().RemoveOperation(operation); Assert.AreEqual(0, operationContainers.Single().Operations.Count()); var iterationIid = new Guid("b58ea73d-350d-4520-b9d9-a52c75ac2b5d"); var iterationSetup = new IterationSetup(Guid.NewGuid(), 0); var iterationSetupPoco = new CDP4Common.SiteDirectoryData.IterationSetup(iterationSetup.Iid, cache, this.credentials.Uri); var model = new EngineeringModel(Guid.NewGuid(), cache, this.credentials.Uri); var modelSetup = new CDP4Common.SiteDirectoryData.EngineeringModelSetup(); modelSetup.ActiveDomain.Add(domainSys); var source = new ReferenceSource(Guid.NewGuid(), cache, this.credentials.Uri) { Publisher = new Organization(Guid.NewGuid(), cache, this.credentials.Uri) { Container = this.siteDirectoryData } }; var requiredRdl = new ModelReferenceDataLibrary { RequiredRdl = new SiteReferenceDataLibrary(), ReferenceSource = { source } }; var person = new Person { ShortName = "admin", Organization = organization, DefaultDomain = domainAer }; var participant = new Participant(Guid.NewGuid(), cache, this.credentials.Uri) { Person = person }; participant.Person.Role = role; participant.Role = participantRole; participant.Domain.Add(domainSys); participant.Domain.Add(domainProp); modelSetup.Participant.Add(participant); var lazyPerson = new Lazy <Thing>(() => person); var iterationPoco = new CDP4Common.EngineeringModelData.Iteration(iterationIid, cache, this.credentials.Uri) { IterationSetup = iterationSetupPoco }; model.Iteration.Add(iterationPoco); var iteration = (Iteration)iterationPoco.ToDto(); model.EngineeringModelSetup = modelSetup; this.siteDirectoryData.Model.Add(modelSetup); modelSetup.RequiredRdl.Add(requiredRdl); modelSetup.IterationSetup.Add(iterationSetupPoco); cache.TryAdd(new CacheKey(person.Iid, this.siteDirectoryData.Iid), lazyPerson); this.siteDirectoryData.Cache = cache; iteration.IterationSetup = iterationSetup.Iid; var clone1 = iteration.DeepClone <Iteration>(); operation = new Operation(iteration, clone1, OperationKind.Update); var operationContainer = new OperationContainer("/EngineeringModel/" + model.Iid + "/iteration/" + iteration.Iid, 0); operationContainer.AddOperation(operation); operationContainers = new[] { operationContainer, operationContainer }; Assert.IsEmpty(await this.dal.Write(operationContainers, files)); }
public async Task <bool> PackData(string migrationFile) { List <string> extensionFiles = null; var zipCredentials = new Credentials(this.SourceSession.Credentials.UserName, this.TargetSession.Credentials.Password, new Uri(ArchiveFileName)); var zipSession = new Session(this.Dal, zipCredentials); var success = true; if (!string.IsNullOrEmpty(migrationFile)) { if (!System.IO.File.Exists(migrationFile)) { this.NotifyMessage("Unable to find selected migration file.", LogVerbosity.Warn); return(false); } try { extensionFiles = new List <string> { MigrationFileName }; if (System.IO.File.Exists(MigrationFileName)) { System.IO.File.Delete(MigrationFileName); } System.IO.File.Copy(migrationFile, MigrationFileName); } catch (Exception ex) { this.NotifyMessage("Could not add migration.json file.", LogVerbosity.Error, ex); return(false); } } this.NotifyStep(MigrationStep.PackStart); var operationContainers = new List <OperationContainer>(); var openIterations = this.SourceSession.OpenIterations.Select(i => i.Key); foreach (var iteration in openIterations) { var transactionContext = TransactionContextResolver.ResolveContext(iteration); var operationContainer = new OperationContainer(transactionContext.ContextRoute()); var dto = iteration.ToDto(); var operation = new Operation(null, dto, OperationKind.Create); operationContainer.AddOperation(operation); operationContainers.Add(operationContainer); } try { await this.Dal.Write(operationContainers, extensionFiles); } catch (Exception ex) { this.NotifyMessage("Could not pack data.", LogVerbosity.Error, ex); success = false; } finally { await this.SourceSession.Close(); } this.NotifyStep(MigrationStep.PackEnd); return(success); }
/// <summary> /// Method syncing the given <paramref name="selectedIids"/> from the source server to the target server /// </summary> /// <param name="selectedIids"> /// A list of thing iids to sync /// </param> /// <returns> /// The <see cref="Task"/> /// </returns> public override async Task Sync(IEnumerable <Guid> selectedIids) { var operationContainer = new OperationContainer(this.TargetSiteDirectory.Route); var cloneTargetSiteDirectory = this.TargetSiteDirectory.Clone(false); var allTargetThings = this.TargetSiteDirectory.QueryContainedThingsDeep() .ToDictionary(thing => thing.Iid, thing => thing); // sync DomainOfExpertise foreach (var domain in this.SourceSiteDirectory.Domain .Where(t => selectedIids.Contains((t.Iid)))) { var cloneSourceThing = domain.Clone(true); cloneSourceThing.Container = cloneTargetSiteDirectory; var index = cloneTargetSiteDirectory.Domain .FindIndex(t => t.Iid == cloneSourceThing.Iid); if (index == -1) { cloneTargetSiteDirectory.Domain.Add(cloneSourceThing); } else { cloneTargetSiteDirectory.Domain[index] = cloneSourceThing; } foreach (var toBeMovedThing in cloneSourceThing.QueryContainedThingsDeep()) { operationContainer.AddOperation(this.GetOperation(toBeMovedThing, allTargetThings)); } } // sync DomainOfExpertiseGroup foreach (var domainGroup in this.SourceSiteDirectory.DomainGroup .Where(t => selectedIids.Contains((t.Iid)))) { var cloneSourceThing = domainGroup.Clone(true); cloneSourceThing.Container = cloneTargetSiteDirectory; var index = cloneTargetSiteDirectory.DomainGroup .FindIndex(t => t.Iid == cloneSourceThing.Iid); if (index == -1) { cloneTargetSiteDirectory.DomainGroup.Add(cloneSourceThing); } else { cloneTargetSiteDirectory.DomainGroup[index] = cloneSourceThing; } foreach (var toBeMovedThing in cloneSourceThing.QueryContainedThingsDeep()) { operationContainer.AddOperation(this.GetOperation(toBeMovedThing, allTargetThings)); } } // update target SiteDirectory operationContainer.AddOperation(new Operation( this.TargetSiteDirectory.ToDto(), cloneTargetSiteDirectory.ToDto(), OperationKind.Update)); await this.TargetSession.Write(operationContainer); }