} // applyMergeChoices() public void _applyMergeChoicesToNode(MergeInfoData Choices, MergeInfoData.MergeInfoNodePair nodePair, CswNbtNode resultNode) { CswNbtNode Node1 = _CswNbtResources.Nodes[nodePair.Node1Id]; CswNbtNode Node2 = _CswNbtResources.Nodes[nodePair.Node2Id]; if (null != Node1 && null != Node2) { /* * Copy all the values from Node2 into the result and then copy any properties from Node1 into the result that were selected * This is to ensure we copy property values we didn't have to merge. */ resultNode.copyPropertyValuesGeneric(Node2); foreach (MergeInfoData.MergeInfoProperty mergeProp in nodePair.Properties.Where(mergeProp => mergeProp.Choice == 1)) { resultNode.Properties[mergeProp.NodeTypePropId].copyGeneric(Node1.Properties[mergeProp.NodeTypePropId]); } // Set references to new merged node if (Int32.MinValue != nodePair.NodeReferencePropId) { // Find the new nodeid for the value of the reference ICswNbtNodePropNodeReference NodeReferenceProp = resultNode.Properties[nodePair.NodeReferencePropId].AsNodeReference; CswPrimaryKey oldNodeId = NodeReferenceProp.ReferencedNodeId; MergeInfoData.MergeInfoNodePair otherNodePair = Choices.NodePairs.FirstOrDefault(np => np.Node1Id == oldNodeId.ToString() || np.Node2Id == oldNodeId.ToString()); if (null != otherNodePair) { // Set the reference to point to the new merged node NodeReferenceProp.ReferencedNodeId = CswConvert.ToPrimaryKey(otherNodePair.Node2Id); } } // if( Int32.MinValue != nodePair.NodeReferencePropId ) } // if( null != Node1 && null != Node2 ) } // _applyMergeChoicesToNode()
} // _getUniqueKeysDict() public MergeInfoData applyMergeChoices(MergeInfoData Choices) { foreach (MergeInfoData.MergeInfoNodePair nodePair in Choices.NodePairs) { // Apply the changes to a temp node, so that they can be previewed CswNbtNode tempNode; if (false == string.IsNullOrEmpty(nodePair.NodeTempId)) { tempNode = _CswNbtResources.Nodes[nodePair.NodeTempId]; _applyMergeChoicesToNode(Choices, nodePair, tempNode); tempNode.postChanges(ForceUpdate: false, IsCopy: false, OverrideUniqueValidation: true); } else { CswNbtNode Node1 = _CswNbtResources.Nodes[nodePair.Node1Id]; if (null != Node1) { tempNode = _CswNbtResources.Nodes.makeNodeFromNodeTypeId(Node1.NodeTypeId, IsTemp : true, OverrideUniqueValidation : true, OnAfterMakeNode : delegate(CswNbtNode newNode) { _applyMergeChoicesToNode(Choices, nodePair, newNode); }); nodePair.NodeTempId = tempNode.NodeId.ToString(); nodePair.NodeTempName = tempNode.NodeName; } } } // foreach( MergeInfoData.MergeInfoNodePair nodePair in Choices.NodePairs ) return(Choices); } // applyMergeChoices()
public MergeInfoData getMergeInfo(CswPrimaryKey NodeId1, CswPrimaryKey NodeId2) { MergeInfoData ret = new MergeInfoData(); // Set up the requested merge and all other required merges (recursively) _addMergeNodes(ret, NodeId1, NodeId2); return(ret); } // getMergeInfo()
} // _applyMergeChoicesToNode() public CswNbtView finishMerge(MergeInfoData Choices) { CswNbtView view = new CswNbtView(_CswNbtResources); CswNbtNode firstMergedNode = null; foreach (MergeInfoData.MergeInfoNodePair nodePair in Choices.NodePairs) { // Remove the temp node CswNbtNode NodeTemp = _CswNbtResources.Nodes[nodePair.NodeTempId]; if (null != NodeTemp) { NodeTemp.delete(DeleteAllRequiredRelatedNodes: false, OverridePermissions: true, ValidateRequiredRelationships: false); } // Merge Node1 into Node2, and delete Node1 CswNbtNode Node1 = _CswNbtResources.Nodes[nodePair.Node1Id]; CswNbtNode Node2 = _CswNbtResources.Nodes[nodePair.Node2Id]; if (null != Node1 && null != Node2) { // Store the first node merged to return if (null == firstMergedNode) { firstMergedNode = Node2; } // Apply the merge to Node2 _applyMergeChoicesToNode(Choices, nodePair, Node2); Node2.postChanges(ForceUpdate: false, IsCopy: false, OverrideUniqueValidation: true); // Update any references to point to node2 foreach (MergeInfoData.MergeInfoNodeReference Ref in nodePair.NodeReferences) { CswNbtNode refNode = _CswNbtResources.Nodes[Ref.NodeId]; if (refNode.Properties[Ref.NodeTypePropId].getFieldTypeValue() == CswEnumNbtFieldType.UserSelect) { // Special case: UserSelect refNode.Properties[Ref.NodeTypePropId].AsUserSelect.RemoveUser(Node1.NodeId); refNode.Properties[Ref.NodeTypePropId].AsUserSelect.AddUser(Node2.NodeId); refNode.Properties[Ref.NodeTypePropId].AsUserSelect.SyncGestalt(); } else { // Node Reference refNode.Properties[Ref.NodeTypePropId].AsNodeReference.ReferencedNodeId = Node2.NodeId; refNode.Properties[Ref.NodeTypePropId].AsNodeReference.RefreshNodeName(); } refNode.postChanges(ForceUpdate: false, IsCopy: false, OverrideUniqueValidation: true); } // Delete merged node 1 Node1.delete(DeleteAllRequiredRelatedNodes: false, OverridePermissions: true, ValidateRequiredRelationships: false); } // if( null != Node1 && null != Node2 ) } // foreach( MergeInfoData.MergeInfoNodePair nodePair in Choices.NodePairs ) // Return a view of the first merged node if (null != firstMergedNode) { view = firstMergedNode.getViewOfNode(includeDefaultFilters: false); } return(view); } // finishMerge()
} // getMergeInfo() private void _addMergeNodes(MergeInfoData ret, CswPrimaryKey NodeId1, CswPrimaryKey NodeId2, CswNbtMetaDataNodeTypeProp NodeReferenceProp = null) { CswNbtNode Node1 = _CswNbtResources.Nodes[NodeId1]; CswNbtNode Node2 = _CswNbtResources.Nodes[NodeId2]; if (null != Node1 && null != Node2) { // Make sure there isn't already a node pair for these nodes if (false == ret.NodePairs.Any(np => (np.Node1Id == Node1.NodeId.ToString() && np.Node2Id == Node2.NodeId.ToString()) || (np.Node1Id == Node2.NodeId.ToString() && np.Node2Id == Node1.NodeId.ToString()))) { CswNbtMetaDataNodeType Node1NT = Node1.getNodeType(); MergeInfoData.MergeInfoNodePair NodePair = new MergeInfoData.MergeInfoNodePair(); NodePair.NodeReferences = new Collection <MergeInfoData.MergeInfoNodeReference>(); NodePair.NodeTypeName = Node1NT.NodeTypeName; NodePair.Node1Id = Node1.NodeId.ToString(); NodePair.Node2Id = Node2.NodeId.ToString(); NodePair.Node1Name = Node1.NodeName; NodePair.Node2Name = Node2.NodeName; if (null != NodeReferenceProp) { NodePair.NodeReferencePropId = NodeReferenceProp.PropId; } else { NodePair.NodeReferencePropId = Int32.MinValue; } foreach (CswNbtNodePropWrapper Prop1 in Node1.Properties.Where(p => (null == NodeReferenceProp || p.NodeTypePropId != NodeReferenceProp.PropId))) { CswNbtNodePropWrapper Prop2 = Node2.Properties[Prop1.NodeTypePropId]; if (null == Prop2 || Prop1.Gestalt != Prop2.Gestalt) { NodePair.Properties.Add(new MergeInfoData.MergeInfoProperty() { PropName = Prop1.PropName, NodeTypePropId = Prop1.NodeTypePropId, Node1Value = Prop1.Gestalt, Node2Value = Prop2.Gestalt }); } // if( null == Prop2 || Prop1.Gestalt != Prop2.Gestalt ) } // foreach( CswNbtNodePropWrapper Prop1 in Node1.Properties ) ret.NodePairs.Add(NodePair); // If two nodes that formerly related to each of node1 and node2 now relate to the merged target, // and they now would be compound unique violations, we have to merge those too. // First, find references that point to the merged nodes foreach (CswNbtMetaDataNodeTypeProp thisProp in _CswNbtResources.MetaData.getNodeTypeProps().Where(p => p.IsNodeReference() && p.FkMatches(Node1.getNodeType()))) { // Find unique key sets for nodes using this reference that point to either node1 or node2 Dictionary <CswDelimitedString, CswPrimaryKey> Node1UniqueKeysDict = _getUniqueKeysDict(NodePair, Node1, thisProp); Dictionary <CswDelimitedString, CswPrimaryKey> Node2UniqueKeysDict = _getUniqueKeysDict(NodePair, Node2, thisProp); // Look for redundant keys to indicate a potential unique violation foreach (CswDelimitedString key in Node1UniqueKeysDict.Keys) { if (Node2UniqueKeysDict.ContainsKey(key)) { // unique violation! gotta merge these too. _addMergeNodes(ret, Node1UniqueKeysDict[key], Node2UniqueKeysDict[key], thisProp); } } // foreach( CswDelimitedString key in Node1UniqueKeysDict.Keys ) } // foreach( CswNbtMetaDataNodeTypeProp thisProp in _CswNbtResources.MetaData.getNodeTypeProps().Where( p => p.IsNodeReference() ) ) // Special case: UserSelect properties if (Node1NT.getObjectClassValue() == CswEnumNbtObjectClass.UserClass) { foreach (CswNbtMetaDataNodeTypeProp thisUserSelProp in _CswNbtResources.MetaData.getNodeTypeProps(CswEnumNbtFieldType.UserSelect)) { // Create a view of nodes that point to either merged node via this reference CswNbtView view = new CswNbtView(_CswNbtResources); CswNbtViewRelationship rel1 = view.AddViewRelationship(thisUserSelProp.getNodeType(), false); view.AddViewPropertyAndFilter(rel1, thisUserSelProp, Conjunction: CswEnumNbtFilterConjunction.And, FilterMode: CswEnumNbtFilterMode.Contains, Value: Node1.NodeId.PrimaryKey.ToString()); view.AddViewPropertyAndFilter(rel1, thisUserSelProp, Conjunction: CswEnumNbtFilterConjunction.Or, FilterMode: CswEnumNbtFilterMode.Contains, Value: Node2.NodeId.PrimaryKey.ToString()); // Add nodes with matching UserSelect properties to NodeReferences for later updating ICswNbtTree tree = _CswNbtResources.Trees.getTreeFromView(view, RequireViewPermissions: false, IncludeHiddenNodes: true, IncludeSystemNodes: true); for (Int32 c = 0; c < tree.getChildNodeCount(); c++) { tree.goToNthChild(c); NodePair.NodeReferences.Add(new MergeInfoData.MergeInfoNodeReference() { NodeId = tree.getNodeIdForCurrentPosition().ToString(), NodeTypePropId = thisUserSelProp.PropId }); tree.goToParentNode(); } // for( Int32 c = 0; c < tree.getChildNodeCount(); c++ ) } // foreach( CswNbtMetaDataNodeTypeProp thisUserSelProp in _CswNbtResources.MetaData.getNodeTypeProps( CswEnumNbtFieldType.UserSelect ) ) } // if( Node1NT.getObjectClassValue() == CswEnumNbtObjectClass.UserClass ) } // if(false == ret.NodePairs.Any( ... )) } // if( null != Node1 && null != Node2 ) } // _addMergeNodes()