/// <inheritdoc/> protected override object TransformForSerialization(ITypeDescriptor descriptor, object collection) { var instance = CreatEmptyContainer(descriptor); CollectionItemIdentifiers identifier; if (!CollectionItemIdHelper.TryGetCollectionItemIds(collection, out identifier)) { identifier = new CollectionItemIdentifiers(); } var i = 0; foreach (var item in (IEnumerable)collection) { ItemId id; if (!identifier.TryGet(i, out id)) { id = ItemId.New(); identifier.Add(i, id); } instance.Add(id, item); ++i; } return(instance); }
protected override void UpdateAssetFromSource(ModelAsset assetToMerge) { // Create a dictionary containing all new and old materials, favoring old ones to maintain existing references var dictionary = assetToMerge.Materials.ToDictionary(x => x.Name, x => x); Asset.Materials.ForEach(x => dictionary[x.Name] = x); // Create a dictionary mapping existing materials to their item id, to attempt to maintain existing ids and avoid unnecessary changes. var ids = CollectionItemIdHelper.GetCollectionItemIds(Asset.Materials).ToDictionary(x => Asset.Materials[(int)x.Key].Name, x => x.Value); // Remove currently existing materials, one by one because Quantum does not provide a Clear method. var materialsNode = AssetRootNode[nameof(ModelAsset.Materials)].Target; while (Asset.Materials.Count > 0) { materialsNode.Remove(Asset.Materials[0], new NodeIndex(0)); } // Repopulate the list of materials for (var i = 0; i < assetToMerge.Materials.Count; ++i) { // Retrieve or create an id for the material ItemId id; if (!ids.TryGetValue(assetToMerge.Materials[i].Name, out id)) { id = ItemId.New(); } // Use Restore to allow to set manually the id. materialsNode.Restore(dictionary[assetToMerge.Materials[i].Name], new NodeIndex(i), id); } }
private IEnumerable <Item> _getItems(IEnumerable <RawFileData> files, IProgressionHandler progress) { try { var filteredFiles = files.Where(file => file.Type == FileType.Model).ToArray(); var hashes = filteredFiles.Select(x => x.Hash).ToArray(); var fileCount = filteredFiles.Count(); _logger.LogTrace("creating {0} items: {1}", fileCount, hashes); var res = filteredFiles .GroupBy(fileEx => fileEx.HashKey) .Select(fileGroup => { var itemId = ItemId.New(); return(new Item( ItemName.From(fileGroup.First().Path.GetFilenameWithoutExtension().Value), null, new ItemVersion( itemId, fileGroup.Key, new Version(1, 0, 0), fileGroup.Select(file => file.GetFileData()) ).AsArray(), itemId)); }).ToArray(); progress.Current++; _logger.LogInformation("created {0} items with a total of {1} Versions", res.Count(), res.SelectMany(item => item.Versions).Count()); return(res); } catch (Exception ex) { _logger.LogError(ex, "item-creation failed"); return(null); } }
/// <inheritdoc/> protected override object TransformForSerialization(ITypeDescriptor descriptor, object collection) { var dictionaryDescriptor = (DictionaryDescriptor)descriptor; var instance = CreatEmptyContainer(descriptor); CollectionItemIdentifiers identifier; if (!CollectionItemIdHelper.TryGetCollectionItemIds(collection, out identifier)) { identifier = new CollectionItemIdentifiers(); } var keyWithIdType = typeof(KeyWithId <>).MakeGenericType(dictionaryDescriptor.KeyType); foreach (var item in dictionaryDescriptor.GetEnumerator(collection)) { ItemId id; if (!identifier.TryGet(item.Key, out id)) { id = ItemId.New(); identifier.Add(item.Key, id); } var keyWithId = Activator.CreateInstance(keyWithIdType, id, item.Key); instance.Add(keyWithId, item.Value); } return(instance); }
private Item createTestEntity() => new Item( ItemId.New(), (ItemName)"itenName", new string[] { "tag 1", "tag 2" }.Select(x => (Tag)x).ToArray(), DateTime.Now.AddMinutes(-5), DateTime.Now);
public Item( ItemName name, IEnumerable <Tag> tags = null, IEnumerable <ItemVersion> versions = null, ItemId?id = null) : this(id ?? ItemId.New(), name, tags, versions, DateTime.Now) { }
public static YamlAssetPath FromMemberPath([NotNull] MemberPath path, object root) { if (path == null) { throw new ArgumentNullException(nameof(path)); } var result = new YamlAssetPath(); var clone = new MemberPath(); foreach (var item in path.Decompose()) { if (item.MemberDescriptor != null) { clone.Push(item.MemberDescriptor); var member = item.MemberDescriptor.Name; result.PushMember(member); } else { object index = null; if (item is MemberPath.ArrayPathItem arrayItem) { clone.Push(arrayItem.Descriptor, arrayItem.Index); index = arrayItem.Index; } else if (item is MemberPath.CollectionPathItem collectionItem) { clone.Push(collectionItem.Descriptor, collectionItem.Index); index = collectionItem.Index; } else if (item is MemberPath.DictionaryPathItem dictionaryItem) { clone.Push(dictionaryItem.Descriptor, dictionaryItem.Key); index = dictionaryItem.Key; } else if (item is MemberPath.SetPathItem setItem) { clone.Push(setItem.Descriptor, setItem.Index); index = setItem.Index; } if (!CollectionItemIdHelper.TryGetCollectionItemIds(clone.GetValue(root), out CollectionItemIdentifiers ids)) { result.PushIndex(index); } else { var id = ids[index]; // Create a new id if we don't have any so far if (id == ItemId.Empty) { id = ItemId.New(); } result.PushItemId(id); } } } return(result); }
private FileItemLink createTestEntity() => new FileItemLink( FileItemLinkId.New(), ItemId.New(), new FileInfoHashKey(FileInfoDtoTests.createTestEntity()), null, new Version(1, 2, 3), DateTime.Now.AddMinutes(-5), DateTime.Now);
private ElementInfo GetElement(string name) { _elementInfoId++; return (new ElementInfo( new ProductInfo(_elementInfoId, name), ItemId.New(), 1)); }
public override void VisitDictionary(object dictionary, DictionaryDescriptor descriptor) { if (ShouldGenerateItemIdCollection(dictionary)) { var itemIds = CollectionItemIdHelper.GetCollectionItemIds(dictionary); foreach (var element in descriptor.GetEnumerator(dictionary)) { itemIds.Add(element.Key, ItemId.New()); } } }
public override void VisitArray(Array array, ArrayDescriptor descriptor) { if (ShouldGenerateItemIdCollection(array)) { var itemIds = CollectionItemIdHelper.GetCollectionItemIds(array); for (var i = 0; i < array.Length; ++i) { itemIds.Add(i, ItemId.New()); } } base.VisitArray(array, descriptor); }
public static YamlAssetPath ConvertPath(GraphNodePath path, int inNonIdentifiableType) { var currentNode = (AssetNode)path.RootNode; var result = new YamlAssetPath(); var i = 0; foreach (var item in path.Path) { switch (item.Type) { case GraphNodePath.ElementType.Member: var member = (string)item.Value; result.PushMember(member); currentNode = (AssetNode)((IGraphNode)currentNode).TryGetChild(member); break; case GraphNodePath.ElementType.Target: if (i < path.Path.Count - 1) { currentNode = (AssetNode)((IGraphNode)currentNode).Target; } break; case GraphNodePath.ElementType.Index: var index = (Index)item.Value; if (inNonIdentifiableType > 0 || currentNode.IsNonIdentifiableCollectionContent) { result.PushIndex(index.Value); } else { var id = currentNode.IndexToId(index); // Create a new id if we don't have any so far if (id == ItemId.Empty) { id = ItemId.New(); } result.PushItemId(id); } if (i < path.Path.Count - 1) { currentNode = (AssetNode)((IGraphNode)currentNode).IndexedTarget(index); } break; default: throw new ArgumentOutOfRangeException(); } ++i; } return(result); }
public override void VisitSet(IEnumerable set, SetDescriptor descriptor) { if (ShouldGenerateItemIdCollection(set)) { IEnumerator enumerator = (set as IEnumerable).GetEnumerator(); var itemIds = CollectionItemIdHelper.GetCollectionItemIds(set); while (enumerator.MoveNext()) { itemIds.Add(enumerator.Current, ItemId.New()); } } base.VisitSet(set, descriptor); }
public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor) { if (ShouldGenerateItemIdCollection(collection)) { var itemIds = CollectionItemIdHelper.GetCollectionItemIds(collection); var count = descriptor.GetCollectionCount(collection); for (var i = 0; i < count; ++i) { itemIds.Add(i, ItemId.New()); } } base.VisitCollection(collection, descriptor); }
public override void VisitArray(Array array, ArrayDescriptor descriptor) { CollectionItemIdentifiers itemIds; if (inNonIdentifiableType == 0 && !CollectionItemIdHelper.TryGetCollectionItemIds(array, out itemIds)) { itemIds = CollectionItemIdHelper.GetCollectionItemIds(array); for (var i = 0; i < array.Length; ++i) { itemIds.Add(i, ItemId.New()); } } base.VisitArray(array, descriptor); }
public override void VisitDictionary(object dictionary, DictionaryDescriptor descriptor) { CollectionItemIdentifiers itemIds; if (inNonIdentifiableType == 0 && !CollectionItemIdHelper.TryGetCollectionItemIds(dictionary, out itemIds)) { itemIds = CollectionItemIdHelper.GetCollectionItemIds(dictionary); foreach (var element in descriptor.GetEnumerator(dictionary)) { itemIds.Add(element.Key, ItemId.New()); } } base.VisitDictionary(dictionary, descriptor); }
public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor) { CollectionItemIdentifiers itemIds; if (inNonIdentifiableType == 0 && !CollectionItemIdHelper.TryGetCollectionItemIds(collection, out itemIds)) { itemIds = CollectionItemIdHelper.GetCollectionItemIds(collection); var count = descriptor.GetCollectionCount(collection); for (var i = 0; i < count; ++i) { itemIds.Add(i, ItemId.New()); } } base.VisitCollection(collection, descriptor); }
/// <summary> /// Fixes up the <see cref="CollectionItemIdentifiers"/> of a collection by generating new ids if there are any duplicate. /// </summary> /// <param name="collection">The collection to fix up.</param> /// <remarks>This method doesn't handle collections in derived objects that will be desynchronized afterwards.</remarks> private void Fixup(object collection) { CollectionItemIdentifiers itemIds; if (CollectionItemIdHelper.TryGetCollectionItemIds(collection, out itemIds)) { var items = new HashSet <ItemId>(); var localCopy = new CollectionItemIdentifiers(); itemIds.CloneInto(localCopy, null); foreach (var id in localCopy) { if (!items.Add(id.Value)) { logger?.Warning($"Duplicate item identifier [{id.Value}] in collection {CurrentPath} of asset [{assetItem.Location}]. Generating a new identifier to remove the duplicate entry."); itemIds[id.Key] = ItemId.New(); } } } }
public TestEnvironmentObject(TestEnvironmentCreateContext createContext, ITestMocks mocks) { _productsTable = createContext.Products; ElementInfos = new TestDbObjectList <string, ElementInfo>( k => { var p = Products.Get(k); return(new ElementInfo(p.Info, ItemId.New(), 1)); }); //Prices = new Dictionary<string, ElementPrice>(); SalesOrderEntities = createContext.Documents.SalesOrderEntities; DocumentFactories = new DocumentFactoryProvider(this); Products = new ProductsProvider(createContext.Products); Mocks = mocks; }
protected override void UpdateAssetFromSource(SkeletonAsset assetToMerge) { // Create a dictionary containing all new and old nodes, favoring old ones to maintain existing references var dictionary = assetToMerge.Nodes.ToDictionary(x => x.Name, x => x); Asset.Nodes.ForEach(x => dictionary[x.Name] = x); // Create a dictionary mapping existing materials to their item id, to attempt to maintain existing ids and avoid unnecessary changes. var ids = CollectionItemIdHelper.GetCollectionItemIds(Asset.Nodes).ToDictionary(x => Asset.Nodes[(int)x.Key].Name, x => x.Value); // Remove currently existing nodes, one by one because Quantum does not provide a Clear method. var skeletonNodes = AssetRootNode[nameof(SkeletonAsset.Nodes)].Target; while (Asset.Nodes.Count > 0) { skeletonNodes.Remove(Asset.Nodes[0], new NodeIndex(0)); } // Repopulate the list of nodes for (var i = 0; i < assetToMerge.Nodes.Count; ++i) { // Information such as Depth has to come from the new asset var newNode = assetToMerge.Nodes[i]; // Information such as Preserve should come from the merged dictionary. newNode.Preserve = dictionary[assetToMerge.Nodes[i].Name].Preserve; // Retrieve or create an id for the node ItemId id; if (!ids.TryGetValue(assetToMerge.Nodes[i].Name, out id)) { id = ItemId.New(); } skeletonNodes.Restore(newNode, new NodeIndex(i), id); } }
public Item() { Id = ItemId.New(); }
internal void OnItemChanged(object sender, ItemChangeEventArgs e) { var value = node.Retrieve(); if (!CollectionItemIdHelper.HasCollectionItemIds(value)) { return; } // Make sure that we have item ids everywhere we're supposed to. AssetCollectionItemIdHelper.GenerateMissingItemIds(e.Collection.Retrieve()); // Clear the cached item identifier collection. collectionItemIdentifiers = null; // Create new ids for collection items var baseNode = (AssetObjectNode)BaseNode; var removedId = ItemId.Empty; var isOverriding = baseNode != null && !PropertyGraph.UpdatingPropertyFromBase; var itemIds = CollectionItemIdHelper.GetCollectionItemIds(value); var collectionDescriptor = node.Descriptor as CollectionDescriptor; switch (e.ChangeType) { case ContentChangeType.CollectionUpdate: break; case ContentChangeType.CollectionAdd: { // Compute the id we will add for this item var itemId = restoringId != ItemId.Empty ? restoringId : ItemId.New(); // Add the id to the proper location (insert or add) if (collectionDescriptor != null) { if (e.Index == Index.Empty) { throw new InvalidOperationException("An item has been added to a collection that does not have a predictable Add. Consider using NonIdentifiableCollectionItemsAttribute on this collection."); } itemIds.Insert(e.Index.Int, itemId); } else { itemIds[e.Index.Value] = itemId; } break; } case ContentChangeType.CollectionRemove: { var itemId = itemIds[e.Index.Value]; // update isOverriding, it should be true only if the item being removed exist in the base. isOverriding = isOverriding && baseNode.HasId(itemId); removedId = collectionDescriptor != null?itemIds.DeleteAndShift(e.Index.Int, isOverriding) : itemIds.Delete(e.Index.Value, isOverriding); break; } default: throw new ArgumentOutOfRangeException(); } // Don't update override if propagation from base is disabled. if (PropertyGraph?.Container?.PropagateChangesFromBase == false) { return; } // Mark it as New if it does not come from the base if (!ResettingOverride) { if (e.ChangeType != ContentChangeType.CollectionRemove && isOverriding) { // If it's an add or an updating, there is no scenario where we can be "un-overriding" without ResettingOverride, so we pass true. OverrideItem(true, e.Index); } else if (e.ChangeType == ContentChangeType.CollectionRemove) { // If it's a delete, it could be an item that was previously added as an override, and that should not be marked as "deleted-overridden", so we pass isOverriding OverrideDeletedItem(isOverriding, removedId); } } }
/// <inheritdoc/> protected override void TransformObjectAfterRead(ref ObjectContext objectContext) { if (!AreCollectionItemsIdentifiable(ref objectContext)) { base.TransformObjectAfterRead(ref objectContext); return; } var info = (InstanceInfo)objectContext.Properties[InstanceInfoKey]; // This is to be backward compatible with previous serialization. We fetch ids from the ~Id member of each item if (info.Instance != null) { ICollection <ItemId> deletedItems; objectContext.Properties.TryGetValue(DeletedItemsKey, out deletedItems); TransformAfterDeserialization((IDictionary)objectContext.Instance, info.Descriptor, info.Instance, deletedItems); } objectContext.Instance = info.Instance; var enumerable = objectContext.Instance as IEnumerable; if (enumerable != null) { var ids = CollectionItemIdHelper.GetCollectionItemIds(objectContext.Instance); var descriptor = (DictionaryDescriptor)info.Descriptor; foreach (var item in descriptor.GetEnumerator(objectContext.Instance)) { ItemId id; if (ids.TryGet(item.Key, out id) && id != ItemId.Empty) { continue; } var guid = item.Value != null?IdentifiableHelper.GetId(item.Value) : Guid.NewGuid(); ids[item.Key] = guid != Guid.Empty ? new ItemId(guid.ToByteArray()) : ItemId.New(); } } base.TransformObjectAfterRead(ref objectContext); }
private void ContentChanged(object sender, ContentChangeEventArgs e) { // Make sure that we have item ids everywhere we're supposed to. AssetCollectionItemIdHelper.GenerateMissingItemIds(e.Content.Retrieve()); var node = (AssetNode)e.Content.OwnerNode; if (node.IsNonIdentifiableCollectionContent) { return; } // Create new ids for collection items var baseNode = (AssetNode)BaseContent?.OwnerNode; var isOverriding = !baseNode?.contentUpdating == true; var removedId = ItemId.Empty; switch (e.ChangeType) { case ContentChangeType.ValueChange: break; case ContentChangeType.CollectionAdd: { var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor; var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve()); // Compute the id we will add for this item ItemId itemId; if (baseNode?.contentUpdating == true) { var baseCollection = baseNode.Content.Retrieve(); var baseIds = CollectionItemIdHelper.GetCollectionItemIds(baseCollection); itemId = itemIds.FindMissingId(baseIds); } else { itemId = restoringId != ItemId.Empty ? restoringId : ItemId.New(); } // Add the id to the proper location (insert or add) if (collectionDescriptor != null) { if (e.Index != Index.Empty) { itemIds.Insert(e.Index.Int, itemId); } else { throw new InvalidOperationException("An item has been added to a collection that does not have a predictable Add. Consider using NonIdentifiableCollectionItemsAttribute on this collection."); } } else { itemIds[e.Index.Value] = itemId; } } break; case ContentChangeType.CollectionRemove: { var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor; if (collectionDescriptor != null) { var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve()); removedId = itemIds.DeleteAndShift(e.Index.Int, isOverriding); } else { var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve()); removedId = itemIds.Delete(e.Index.Value, isOverriding); } } break; default: throw new ArgumentOutOfRangeException(); } // Don't update override if propagation from base is disabled. if (PropertyGraph?.Container?.PropagateChangesFromBase == false) { return; } // Mark it as New if it does not come from the base if (!baseNode?.contentUpdating == true && !ResettingOverride) { if (e.ChangeType != ContentChangeType.CollectionRemove) { if (e.Index == Index.Empty) { OverrideContent(!ResettingOverride); } else { OverrideItem(!ResettingOverride, e.Index); } } else { OverrideDeletedItem(true, removedId); } } }
public static YamlAssetPath ConvertPath(GraphNodePath path, int inNonIdentifiableType) { var currentNode = (IAssetNode)path.RootNode; var result = new YamlAssetPath(); var i = 0; foreach (var item in path.Path) { switch (item.Type) { case GraphNodePath.ElementType.Member: var member = (string)item.Value; result.PushMember(member); var objectNode = currentNode as IObjectNode; if (objectNode == null) { throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]"); } currentNode = (IAssetNode)objectNode.TryGetChild(member); break; case GraphNodePath.ElementType.Target: if (i < path.Path.Count - 1) { var targetingMemberNode = currentNode as IMemberNode; if (targetingMemberNode == null) { throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]"); } currentNode = (IAssetNode)targetingMemberNode.Target; } break; case GraphNodePath.ElementType.Index: var index = (Index)item.Value; var memberNode = currentNode as AssetMemberNode; if (memberNode == null) { throw new InvalidOperationException($"An AssetMemberNode was expected when processing the path [{path}]"); } if (inNonIdentifiableType > 0 || memberNode.IsNonIdentifiableCollectionContent) { result.PushIndex(index.Value); } else { var id = memberNode.IndexToId(index); // Create a new id if we don't have any so far if (id == ItemId.Empty) { id = ItemId.New(); } result.PushItemId(id); } if (i < path.Path.Count - 1) { currentNode = (IAssetNode)currentNode.IndexedTarget(index); } break; default: throw new ArgumentOutOfRangeException(); } ++i; } return(result); }
/// <inheritdoc/> protected override void TransformObjectAfterRead(ref ObjectContext objectContext) { InstanceInfo info; if (!objectContext.Properties.TryGetValue(InstanceInfoKey, out info)) { base.TransformObjectAfterRead(ref objectContext); if (AreCollectionItemsIdentifiable(ref objectContext)) { // This is to be backward compatible with previous serialization. We fetch ids from the ~Id member of each item var enumerable = objectContext.Instance as IEnumerable; if (enumerable != null) { var ids = CollectionItemIdHelper.GetCollectionItemIds(objectContext.Instance); var i = 0; foreach (var item in enumerable) { var id = item != null?IdentifiableHelper.GetId(item) : Guid.NewGuid(); ids[i] = id != Guid.Empty ? new ItemId(id.ToByteArray()) : ItemId.New(); ++i; } } } return; } var instance = info.Instance ?? objectContext.SerializerContext.ObjectFactory.Create(info.Descriptor.Type); ICollection <ItemId> deletedItems; objectContext.Properties.TryGetValue(DeletedItemsKey, out deletedItems); TransformAfterDeserialization((IDictionary)objectContext.Instance, info.Descriptor, instance, deletedItems); objectContext.Instance = instance; base.TransformObjectAfterRead(ref objectContext); }
public static YamlAssetPath ConvertPath([NotNull] GraphNodePath path, int inNonIdentifiableType = 0) { if (path == null) { throw new ArgumentNullException(nameof(path)); } var currentNode = (IAssetNode)path.RootNode; var result = new YamlAssetPath(); var i = 0; foreach (var item in path.Path) { switch (item.Type) { case GraphNodePath.ElementType.Member: { var member = item.Name; result.PushMember(member); var objectNode = currentNode as IObjectNode; if (objectNode == null) { throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]"); } currentNode = (IAssetNode)objectNode.TryGetChild(member); break; } case GraphNodePath.ElementType.Target: { if (i < path.Path.Count - 1) { var targetingMemberNode = currentNode as IMemberNode; if (targetingMemberNode == null) { throw new InvalidOperationException($"An IMemberNode was expected when processing the path [{path}]"); } currentNode = (IAssetNode)targetingMemberNode.Target; } break; } case GraphNodePath.ElementType.Index: { var index = item.Index; var objectNode = currentNode as AssetObjectNode; if (objectNode == null) { throw new InvalidOperationException($"An IObjectNode was expected when processing the path [{path}]"); } if (inNonIdentifiableType > 0 || !CollectionItemIdHelper.HasCollectionItemIds(objectNode.Retrieve())) { result.PushIndex(index.Value); } else { var id = objectNode.IndexToId(index); // Create a new id if we don't have any so far if (id == ItemId.Empty) { id = ItemId.New(); } result.PushItemId(id); } if (i < path.Path.Count - 1) { currentNode = (IAssetNode)objectNode.IndexedTarget(index); } break; } default: throw new ArgumentOutOfRangeException(); } ++i; } return(result); }