/// <summary> /// Merges the object definitions. /// </summary> protected void mergeObjectDefinitions() { foreach (var objectDefinition in changeTree.ObjectTreeRoots) { ObjectValue objectValue = objectDefinition.Key; MemoryIndexTreeNode treeNode = objectDefinition.Value; IObjectDescriptor targetDescriptor; bool containsTargetDescriptor = targetStructure.TryGetDescriptor(objectValue, out targetDescriptor); bool alwaysDefined = true; List <ContainerContext> sourceContainers = new List <ContainerContext>(); // Iterate sources to collect object descriptors foreach (SnapshotContext context in snapshotContexts) { IObjectDescriptor descriptor; if (context.SourceStructure.TryGetDescriptor(objectValue, out descriptor)) { // Source contains object - add descriptor to sources sourceContainers.Add(new ContainerContext(context, descriptor)); if (targetDescriptor == null) { // Descriptor is not in the target structure - use current as target targetDescriptor = descriptor; } } else { // Object is at least once undefined - weak merge alwaysDefined = false; } } // Merge object descriptor and prepare operations of modified fields if (targetDescriptor != null) { ObjectTargetContainerContext objectContext = new ObjectTargetContainerContext(writeableTargetStructure, targetDescriptor); createAndEnqueueOperations(objectContext, treeNode, sourceContainers, alwaysDefined); // Save updated descriptor if instance changed or is not stored in target if (isStructureWriteable) { IObjectDescriptor currentDescriptor = objectContext.getCurrentDescriptor(); if (!containsTargetDescriptor || currentDescriptor != targetDescriptor) { writeableTargetStructure.SetDescriptor(objectValue, currentDescriptor); } } } } }
/// <summary> /// Creates the merge operation for all fields of specified object. /// </summary> /// <param name="objectValue">The object value.</param> private void mergeObject(ObjectValue objectValue) { IObjectDescriptorBuilder builder = Factories.StructuralContainersFactories.ObjectDescriptorFactory.CreateObjectDescriptor(writeableStrucure, objectValue, null, ObjectIndex.CreateUnknown(objectValue)) .Builder(writeableStrucure); ContainerOperations collectVariables = new ContainerOperations(this, builder, builder.UnknownIndex, builder.UnknownIndex); foreach (Snapshot snapshot in sourceSnapshots) { IObjectDescriptor descriptor; if (snapshot.Structure.Readonly.TryGetDescriptor(objectValue, out descriptor)) { collectVariables.CollectIndexes(snapshot, builder.UnknownIndex, descriptor); builder.SetType(descriptor.Type); } else { collectVariables.SetUndefined(); } } collectVariables.MergeContainers(); writeableStrucure.SetDescriptor(objectValue, builder.Build(writeableStrucure)); }
/// <summary> /// Merges the arrays into the target index and clear inner collection. /// </summary> /// <param name="targetSnapshot">The target snapshot.</param> /// <param name="targetIndex">Index of the target.</param> /// <param name="operation">The operation.</param> public void MergeArraysAndClear(Snapshot targetSnapshot, MemoryIndex targetIndex, MergeOperation operation) { if (hasArray) { if (targetArray == null) { targetArray = targetSnapshot.CreateArray(); } IArrayDescriptor targetArrayDescriptor; if (!writeableTargetStructure.TryGetDescriptor(targetArray, out targetArrayDescriptor)) { // Target does not contain array - create and add new in target snapshot targetArrayDescriptor = worker.Factories.StructuralContainersFactories.ArrayDescriptorFactory.CreateArrayDescriptor(writeableTargetStructure, targetArray, targetIndex); writeableTargetStructure.SetDescriptor(targetArray, targetArrayDescriptor); writeableTargetStructure.NewIndex(targetArrayDescriptor.UnknownIndex); writeableTargetStructure.SetArray(targetIndex, targetArray); } // Create context and merge descriptors var arrayContext = new ArrayTargetContainerContext(writeableTargetStructure, targetArrayDescriptor); worker.CreateAndEnqueueOperations(arrayContext, operation.TreeNode, sourceArrays, arrayAlwaysDefined && !operation.IsUndefined); // Update current descriptor when changed IArrayDescriptor currentDescriptor = arrayContext.getCurrentDescriptor(); if (currentDescriptor != targetArrayDescriptor) { writeableTargetStructure.SetDescriptor(targetArray, currentDescriptor); } sourceArrays.Clear(); hasArray = false; targetArray = null; } else if (targetArray != null) { worker.DeleteArray(targetIndex, targetArray); targetArray = null; } arrayAlwaysDefined = true; }