protected override ObjectReference FindTargetReference(IGraphNode sourceNode, IGraphNode targetNode, ObjectReference sourceReference) { if (sourceReference.Index.IsEmpty) return targetNode.Content.Reference as ObjectReference; // Special case for objects that are identifiable: the object must be linked to the base only if it has the same id if (sourceReference.ObjectValue != null) { if (sourceReference.Index.IsEmpty) { return targetNode.Content.Reference.AsObject; } var sourceAssetNode = (AssetNode)sourceNode; if (sourceAssetNode.IsNonIdentifiableCollectionContent) return null; // Enumerable reference: we look for an object with the same id var targetReference = targetNode.Content.Reference.AsEnumerable; var sourceIds = CollectionItemIdHelper.GetCollectionItemIds(sourceNode.Content.Retrieve()); var targetIds = CollectionItemIdHelper.GetCollectionItemIds(targetNode.Content.Retrieve()); var itemId = sourceIds[sourceReference.Index.Value]; var targetKey = targetIds.GetKey(itemId); return targetReference.FirstOrDefault(x => Equals(x.Index.Value, targetKey)); } // Not identifiable - default applies return base.FindTargetReference(sourceNode, targetNode, sourceReference); }
internal static IReference CreateReference(object objectValue, Type objectType, object index) { if (objectValue != null && !objectType.IsInstanceOfType(objectValue)) throw new ArgumentException(@"objectValue type does not match objectType", "objectValue"); ++creatingReference; IReference reference; var isCollection = HasCollectionReference(objectValue != null ? objectValue.GetType() : objectType); if (objectValue != null && isCollection && index == NotInCollection) { reference = new ReferenceEnumerable((IEnumerable)objectValue, objectType, index); } else { reference = new ObjectReference(objectValue, objectType, index); } --creatingReference; return reference; }
protected override void VisitReference(IGraphNode referencer, ObjectReference reference, GraphNodePath targetPath) { if (ShouldVisitNode(referencer.Content as MemberContent, reference.TargetNode)) { if (reference.TargetNode != null) { // Prevent re-entrancy in the same object if (VisitedLinks.ContainsKey(reference.TargetNode)) return; IGraphNode targetNode; if (VisitedLinks.TryGetValue(referencer, out targetNode)) { ObjectReference targetReference = null; if (targetNode != null) targetReference = linker.FindTargetReference(referencer, targetNode, reference); VisitedLinks.Add(reference.TargetNode, targetReference?.TargetNode); } } base.VisitReference(referencer, reference, targetPath); } }
internal static IReference CreateReference(object objectValue, Type objectType, Index index) { if (objectValue != null && !objectType.IsInstanceOfType(objectValue)) throw new ArgumentException(@"objectValue type does not match objectType", nameof(objectValue)); if (!CreatingReference.IsValueCreated) CreatingReference.Value = 0; ++CreatingReference.Value; IReference reference; var isCollection = HasCollectionReference(objectValue?.GetType() ?? objectType); if (objectValue != null && isCollection && index.IsEmpty) { reference = new ReferenceEnumerable((IEnumerable)objectValue, objectType, index); } else { reference = new ObjectReference(objectValue, objectType, index); } --CreatingReference.Value; return reference; }
private void AddObjectReference(IGraphNode referencer, ObjectReference reference) { if (reference.TargetNode == null) throw new QuantumConsistencyException("A resolved reference", "An unresolved reference", referencer); if (referencer.Content.Reference == reference && !Equals(referencer.Content.Value, reference.TargetNode.Content.Value)) throw new QuantumConsistencyException("Referenced node with same content value that its referencer", "Referenced node with different content value that its referencer", referencer); if (reference.TargetGuid != reference.TargetNode.Guid) throw new QuantumConsistencyException("Referenced node with same Guid that the reference", "Referenced node with different Guid that the reference", referencer); references.Enqueue(reference); }
protected override ObjectReference FindTargetReference(IGraphNode sourceNode, IGraphNode targetNode, ObjectReference sourceReference) { if (sourceReference.Index.IsEmpty) return base.FindTargetReference(sourceNode, targetNode, sourceReference); var matchValue = 0; if (sourceReference.TargetNode != null) matchValue = (int)sourceReference.TargetNode.TryGetChild(nameof(SimpleClass.Member1)).Content.Value; var targetReference = targetNode.Content.Reference as ReferenceEnumerable; return targetReference?.FirstOrDefault(x => (int)x.TargetNode.TryGetChild(nameof(SimpleClass.Member1)).Content.Value == matchValue); }
/// <summary> /// Visits an <see cref="ObjectReference"/>. /// </summary> /// <param name="referencer">The node containing the reference to visit.</param> /// <param name="reference">The reference to visit.</param> /// <param name="targetPath">The path of the node targeted by this reference.</param> protected virtual void VisitReference(IGraphNode referencer, ObjectReference reference, GraphNodePath targetPath) { if (ShouldVisitNode(referencer.Content as MemberContent, reference.TargetNode)) { VisitNode(reference.TargetNode, targetPath); } }
/// <summary> /// Finds a reference in a target node to correspond with the given reference from the source node. /// </summary> /// <param name="sourceNode">The source node that contains the reference.</param> /// <param name="targetNode">The target node in which to look for a matching reference.</param> /// <param name="sourceReference">The reference in the source node for which to look for a correspondance in the target node.</param> /// <returns>A reference of the target node corresponding to the given reference in the source node, or null if there is no match.</returns> /// <remarks> /// The source reference can either be directly the <see cref="IContent.Reference"/> of the source node if this reference is /// an <see cref="ObjectReference"/>, or one of the reference contained inside <see cref="IContent.Reference"/> if this reference /// is a <see cref="ReferenceEnumerable"/>. The <see cref="IReference.Index"/> property indicates the index of the reference in this case. /// The default implementation returns a reference in the target node that matches the index of the source reference, if available. /// </remarks> protected virtual ObjectReference FindTargetReference(IGraphNode sourceNode, IGraphNode targetNode, ObjectReference sourceReference) { if (sourceReference.Index.IsEmpty) return targetNode.Content.Reference as ObjectReference; var targetReference = targetNode.Content.Reference as ReferenceEnumerable; return targetReference != null && targetReference.HasIndex(sourceReference.Index) ? targetReference[sourceReference.Index] : null; }
public bool ShouldExpandReference(MemberContent member, ObjectReference reference) => true;