/// <summary> /// The only entry point in the class. This method (plus its private methods) does the work of the class. /// </summary> /// <param name="pathname">Pathname of the split up file that contains <paramref name="element"/>.</param> /// <param name="sortedData">All of the data being collected that will end up as CmObject elments in the rebuilt fwdata file. These are sorted by guid order.</param> /// <param name="element">The xml element to check for a duplicate guid.</param> /// <param name="isOwnSeqNode">Out paramenter that is used by caller.</param> /// <param name="className">The class of <paramref name="element"/>.</param> /// <returns></returns> internal static string CheckForDuplicateGuid(string pathname, SortedDictionary <string, XElement> sortedData, XElement element, out bool isOwnSeqNode, out string className) { var mdc = MetadataCache.MdCache; FdoClassInfo classInfo; isOwnSeqNode = GetClassInfoFromElement(mdc, element, out classInfo, out className); var elementGuid = element.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(); if (!sortedData.ContainsKey(elementGuid)) { return(elementGuid); } // Does LT-12524 "Handle merge in case of conflicting move object to different destination". // This need will manifest itself in the guid already being in 'sortedData' and an exception being thrown. // At this point element has not been flattened, so stuff it owns will still be in it. // That is good, if we go with JohnT's idea of using a new guid for guids that are already in 'sortedData'. // By changing it before flattening, then the owned stuff will get the new one for their ownerguid attrs. // The owned stuff will also be dup, so the idea is to also change their guids right now. [ChangeGuids is recursive down the owning tree.] // Just be sure to change 'elementGuid' to the new one. :-) // The first item added to sortedData has been flattened by this point, but not any following ones. var oldGuid = elementGuid; elementGuid = ChangeGuids(mdc, classInfo, element); using (var listener = new ChorusNotesMergeEventListener(ChorusNotesMergeEventListener.GetChorusNotesFilePath(pathname))) { // Don't try to use something like this: // var contextGenerator = new FieldWorkObjectContextGenerator(); // contextGenerator.GenerateContextDescriptor(element.ToString(), pathname) // it will fail for elements in an owning sequence because in the unflattened form // the object representing a sequence item has element name <ownseq> which won't generate a useful label. var context = FieldWorksMergeServices.GenerateContextDescriptor(pathname, elementGuid, className); listener.EnteringContext(context); // Adding the conflict to the listener, will result in the ChorusNotes file being updated (created if need be.) var conflict = new IncompatibleMoveConflict(className, CmObjectFlatteningService.GetXmlNode(element)) { Situation = new NullMergeSituation() }; // The order of the next three lines is critical. Each prepares state that the following lines use. listener.RecordContextInConflict(conflict); conflict.HtmlDetails = MakeHtmlForIncompatibleMove(conflict, oldGuid, elementGuid, element); listener.ConflictOccurred(conflict); File.WriteAllText(pathname + "." + SharedConstants.dupid, ""); } return(elementGuid); }
/// <summary> /// The only entry point in the class. This method (plus its private methods) does the work of the class. /// </summary> /// <param name="pathname">Pathname of the split up file that contains <paramref name="element"/>.</param> /// <param name="sortedData">All of the data being collected that will end up as CmObject elments in the rebuilt fwdata file. These are sorted by guid order.</param> /// <param name="element">The xml element to check for a duplicate guid.</param> /// <param name="isOwnSeqNode">Out paramenter that is used by caller.</param> /// <param name="className">The class of <paramref name="element"/>.</param> /// <returns></returns> internal static string CheckForDuplicateGuid(string pathname, SortedDictionary<string, XElement> sortedData, XElement element, out bool isOwnSeqNode, out string className) { var mdc = MetadataCache.MdCache; FdoClassInfo classInfo; isOwnSeqNode = GetClassInfoFromElement(mdc, element, out classInfo, out className); var elementGuid = element.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(); if (!sortedData.ContainsKey(elementGuid)) return elementGuid; // Does LT-12524 "Handle merge in case of conflicting move object to different destination". // This need will manifest itself in the guid already being in 'sortedData' and an exception being thrown. // At this point element has not been flattened, so stuff it owns will still be in it. // That is good, if we go with JohnT's idea of using a new guid for guids that are already in 'sortedData'. // By changing it before flattening, then the owned stuff will get the new one for their ownerguid attrs. // The owned stuff will also be dup, so the idea is to also change their guids right now. [ChangeGuids is recursive down the owning tree.] // Just be sure to change 'elementGuid' to the new one. :-) // The first item added to sortedData has been flattened by this point, but not any following ones. var oldGuid = elementGuid; elementGuid = ChangeGuids(mdc, classInfo, element); using (var listener = new ChorusNotesMergeEventListener(ChorusNotesMergeEventListener.GetChorusNotesFilePath(pathname))) { // Don't try to use something like this: // var contextGenerator = new FieldWorkObjectContextGenerator(); // contextGenerator.GenerateContextDescriptor(element.ToString(), pathname) // it will fail for elements in an owning sequence because in the unflattened form // the object representing a sequence item has element name <ownseq> which won't generate a useful label. var context = FieldWorksMergeServices.GenerateContextDescriptor(pathname, elementGuid, className); listener.EnteringContext(context); // Adding the conflict to the listener, will result in the ChorusNotes file being updated (created if need be.) var conflict = new IncompatibleMoveConflict(className, CmObjectFlatteningService.GetXmlNode(element)) { Situation = new NullMergeSituation() }; // The order of the next three lines is critical. Each prepares state that the following lines use. listener.RecordContextInConflict(conflict); conflict.HtmlDetails = MakeHtmlForIncompatibleMove(conflict, oldGuid, elementGuid, element); listener.ConflictOccurred(conflict); File.WriteAllText(pathname + "." + SharedConstants.dupid, ""); } return elementGuid; }