public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) { DataMigrationServices.CheckVersionNumber(domainObjectDtoRepository, 7000057); { // LT-13312 Note some projects may not have these guids. DomainObjectDTO dtoVariantType; if (domainObjectDtoRepository.TryGetValue(LexEntryTypeTags.kguidLexTypPluralVar.ToString(), out dtoVariantType)) AddGlossAppendIfEmpty(domainObjectDtoRepository, dtoVariantType, ".pl"); if (domainObjectDtoRepository.TryGetValue(LexEntryTypeTags.kguidLexTypPastVar.ToString(), out dtoVariantType)) AddGlossAppendIfEmpty(domainObjectDtoRepository, dtoVariantType, ".pst"); } DataMigrationServices.IncrementVersionNumber(domainObjectDtoRepository); }
private static void CheckPhPhonData(DomainObjectDTO dtoPhPhonDataTest, IDomainObjectDTORepository dtoRepos) { var eltWmbPhPhonDataTest = XElement.Parse(dtoPhPhonDataTest.Xml); // get phon rule feats var eltPhonRuleFeatsTest = eltWmbPhPhonDataTest.Element("PhonRuleFeats"); Assert.IsNotNull(eltPhonRuleFeatsTest); var eltObjsurTest = eltPhonRuleFeatsTest.Element("objsur"); Assert.IsNotNull(eltObjsurTest); // get possibility list itself var guidPossibilityListTest = eltObjsurTest.Attribute("guid").Value; Assert.IsNotNull(guidPossibilityListTest); DomainObjectDTO dtoCmPossiblityTest; dtoRepos.TryGetValue(guidPossibilityListTest, out dtoCmPossiblityTest); Assert.IsNotNull(dtoCmPossiblityTest); var eltWmbCmPossibilityListTest = XElement.Parse(dtoCmPossiblityTest.Xml); Assert.IsNotNull(eltWmbCmPossibilityListTest); var attrCmPossiblityListClassTest = eltWmbCmPossibilityListTest.Attribute("class").Value; Assert.AreEqual("CmPossibilityList", attrCmPossiblityListClassTest); var attrCmPossiblityListOwnerGuidTest = eltWmbCmPossibilityListTest.Attribute("ownerguid").Value; Assert.AreEqual(dtoPhPhonDataTest.Guid, attrCmPossiblityListOwnerGuidTest); }
private void ValidateStyleReference(IDomainObjectDTORepository repoDTO, XElement xeStyle, string sRefName) { XElement xeOnly = null; XElement xeObjsur = null; foreach (XElement xeRef in xeStyle.Descendants(sRefName)) { Assert.IsNull(xeOnly, sRefName + " should appear only once in an StStyle object"); xeOnly = xeRef; foreach (XElement xeLink in xeRef.Descendants("objsur")) { Assert.IsNull(xeObjsur, "objsur should appear only once in a " + sRefName + " field"); xeObjsur = xeLink; XAttribute xa = xeObjsur.Attribute("guid"); Assert.IsNotNull(xa, sRefName + "/objsur must have a guid attribute"); DomainObjectDTO dto; Assert.IsTrue(repoDTO.TryGetValue(xa.Value, out dto), sRefName + " must point to a valid object"); Assert.AreEqual("StStyle", dto.Classname, sRefName + " must point to a style"); DomainObjectDTO dtoOwner; Assert.IsTrue(repoDTO.TryGetOwner(xa.Value, out dtoOwner), sRefName + " must point to a style with a valid owner"); Assert.AreEqual("LangProject", dtoOwner.Classname, sRefName + " must point to a style owned by LangProject"); } Assert.IsNotNull(xeObjsur, "objsur should appear once in a " + sRefName + " field"); } }
public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) { DataMigrationServices.CheckVersionNumber(domainObjectDtoRepository, 7000057); { // LT-13312 Note some projects may not have these guids. DomainObjectDTO dtoVariantType; if (domainObjectDtoRepository.TryGetValue(LexEntryTypeTags.kguidLexTypPluralVar.ToString(), out dtoVariantType)) { AddGlossAppendIfEmpty(domainObjectDtoRepository, dtoVariantType, ".pl"); } if (domainObjectDtoRepository.TryGetValue(LexEntryTypeTags.kguidLexTypPastVar.ToString(), out dtoVariantType)) { AddGlossAppendIfEmpty(domainObjectDtoRepository, dtoVariantType, ".pst"); } } DataMigrationServices.IncrementVersionNumber(domainObjectDtoRepository); }
internal static void CheckDtoRemoved(IDomainObjectDTORepository dtoRepos, DomainObjectDTO goner) { DomainObjectDTO dto; if (dtoRepos.TryGetValue(goner.Guid, out dto)) { Assert.Fail("Still has deleted (or zombie) DTO."); } Assert.IsTrue(((DomainObjectDtoRepository)dtoRepos).Goners.Contains(goner)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Sets the ParaContainingOrc property for all ScrFootnotes /// </summary> /// <param name="domainObjectDtoRepository"> /// Repository of all CmObject DTOs available for one migration step. /// </param> /// <remarks> /// The method must add/remove/update the DTOs to the repository, /// as it adds/removes objects as part of it work. /// /// Implementors of this interface should ensure the Repository's /// starting model version number is correct for the step. /// Implementors must also increment the Repository's model version number /// at the end of its migration work. /// /// The method also should normally modify the xml string(s) /// of relevant DTOs, since that string will be used by the main /// data migration calling client (ie. BEP). /// </remarks> /// ------------------------------------------------------------------------------------ public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) { DataMigrationServices.CheckVersionNumber(domainObjectDtoRepository, 7000026); foreach (var scrTxtPara in domainObjectDtoRepository.AllInstancesSansSubclasses("ScrTxtPara")) { XElement para = XElement.Parse(scrTxtPara.Xml); XElement contents = para.Element("Contents"); if (contents == null) { continue; } XElement str = contents.Element("Str"); if (str == null) { continue; } foreach (XElement run in str.Elements("Run")) { XAttribute linkAttr = run.Attribute("ownlink"); if (linkAttr == null) { continue; // Run doesn't contain a link } DomainObjectDTO linkObj; // skip links to missing footnotes - user will have to clean these up later. if (!domainObjectDtoRepository.TryGetValue(linkAttr.Value, out linkObj)) { continue; } XElement footnote = XElement.Parse(linkObj.Xml); if (footnote.Attribute("class").Value != "ScrFootnote") { continue; // Link is not for a footnote } if (footnote.Element("ParaContainingOrc") == null) { // ParaContainingOrc property is not present in the footnote, so it needs // to be added. XElement paraContainingOrcElm = XElement.Parse("<ParaContainingOrc><objsur guid=\"" + scrTxtPara.Guid + "\" t=\"r\" /></ParaContainingOrc>"); footnote.Add(paraContainingOrcElm); DataMigrationServices.UpdateDTO(domainObjectDtoRepository, linkObj, footnote.ToString()); } } } DataMigrationServices.IncrementVersionNumber(domainObjectDtoRepository); }
private void VerifySubpossibilities(IDomainObjectDTORepository repoDto, DomainObjectDTO dtoPoss) { var xePoss = XElement.Parse(dtoPoss.Xml); foreach (var objsur in xePoss.XPathSelectElements("SubPossibilities/objsur")) { var xaGuid = objsur.Attribute("guid"); Assert.IsNotNull(xaGuid, "objsur elements should always have a guid attribute."); var guid = xaGuid.Value; DomainObjectDTO dtoSub; Assert.IsTrue(repoDto.TryGetValue(guid, out dtoSub), "SubPossibility Lists should point to valid objects."); VerifySubpossibilities(repoDto, dtoSub); } }
/// <summary> /// Verify that all LexEntryRef objects point to valid LexEntryType objects. /// </summary> private void VerifyLexEntryRefs(IDomainObjectDTORepository repoDto) { foreach (var dtoRef in repoDto.AllInstancesWithSubclasses("LexEntryRef")) { var xeRef = XElement.Parse(dtoRef.Xml); foreach (var objsur in xeRef.XPathSelectElements("ComplexEntryTypes/objsur")) { var xaGuid = objsur.Attribute("guid"); Assert.IsNotNull(xaGuid, "objsur elements should always have a guid attribute."); var guid = xaGuid.Value; DomainObjectDTO dtoType; Assert.IsTrue(repoDto.TryGetValue(guid, out dtoType), "LexEntryRef.ComplexEntryTypes should point to valid objects."); } foreach (var objsur in xeRef.XPathSelectElements("VariantEntryTypes/objsur")) { var xaGuid = objsur.Attribute("guid"); Assert.IsNotNull(xaGuid, "objsur elements should always have a guid attribute."); var guid = xaGuid.Value; DomainObjectDTO dtoType; Assert.IsTrue(repoDto.TryGetValue(guid, out dtoType), "LexEntryRef.VariantEntryTypes should point to valid objects."); } } }
/// <summary> /// Verify that the ComplexEntryTypes and VariantEntryTypes lists contain all of the /// standard LexEntryType objects, and that that they point only to valid LexEntryType /// objects. /// </summary> private void VerifyTypeLists(IDomainObjectDTORepository repoDto) { foreach (var dtoList in repoDto.AllInstancesWithSubclasses("CmPossibilityList")) { var xeList = XElement.Parse(dtoList.Xml); foreach (var objsur in xeList.XPathSelectElements("Possibilities/objsur")) { var xaGuid = objsur.Attribute("guid"); Assert.IsNotNull(xaGuid, "objsur elements should always have a guid attribute."); var guid = xaGuid.Value; DomainObjectDTO dtoPoss; Assert.IsTrue(repoDto.TryGetValue(guid, out dtoPoss), "Possibility Lists should point to valid objects."); VerifySubpossibilities(repoDto, dtoPoss); } } }
private static void RemoveDanglingReferences( IDomainObjectDTORepository dtoRepos, IEnumerable <DomainObjectDTO> allDtos) { foreach (var currentDto in allDtos) { // Fetch the referred (regular reference or owning reference) to object guids. var referredToGuids = ExtractReferencedObjects(currentDto); // See if it is a dangling ref, where target object has been deleted. foreach (var targetGuid in referredToGuids) { DomainObjectDTO referencedDto; if (dtoRepos.TryGetValue(targetGuid, out referencedDto)) { continue; } // targetGuid is a dangling reference. // Remove the <objsur> element from referring object (kvp Key). // The <objsur> will have its 'guid' attribute set to 'targetGuid'. // This will work for owned as well as standard referenced objects. var targetGuidAsString = targetGuid.ToLower(); var referringDto = dtoRepos.GetDTO(currentDto.Guid); var referringElement = XElement.Parse(referringDto.Xml); var emptyPropElements = new List <XElement>(); foreach (var danglingRef in (referringElement.Descendants("objsur").Where( objSurrElement => objSurrElement.Attribute("guid").Value.ToLower() == targetGuidAsString)).ToList()) { var propElement = danglingRef.Parent; danglingRef.Remove(); if (!propElement.HasAttributes && !propElement.HasElements) { emptyPropElements.Add(propElement); } } foreach (var emptyPropElement in emptyPropElements) { emptyPropElement.Remove(); // Remove now empty property element. } // Reset the xml. referringDto.Xml = referringElement.ToString(); dtoRepos.Update(referringDto); } } }
private static DomainObjectDTO GetListDto(IDomainObjectDTORepository dtoRepos, XElement owningElem, string flidName) { var xPath = flidName + "/objsur"; var objsurElem = owningElem.XPathSelectElement(xPath); if (objsurElem == null) { return(null); } var guid = objsurElem.Attribute("guid").Value; DomainObjectDTO dto; if (dtoRepos.TryGetValue(guid, out dto)) { return(dto); } return(null); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Sets the ParaContainingOrc property for all ScrFootnotes /// </summary> /// <param name="domainObjectDtoRepository"> /// Repository of all CmObject DTOs available for one migration step. /// </param> /// <remarks> /// The method must add/remove/update the DTOs to the repository, /// as it adds/removes objects as part of it work. /// /// Implementors of this interface should ensure the Repository's /// starting model version number is correct for the step. /// Implementors must also increment the Repository's model version number /// at the end of its migration work. /// /// The method also should normally modify the xml string(s) /// of relevant DTOs, since that string will be used by the main /// data migration calling client (ie. BEP). /// </remarks> /// ------------------------------------------------------------------------------------ public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) { DataMigrationServices.CheckVersionNumber(domainObjectDtoRepository, 7000026); foreach (var scrTxtPara in domainObjectDtoRepository.AllInstancesSansSubclasses("ScrTxtPara")) { XElement para = XElement.Parse(scrTxtPara.Xml); XElement contents = para.Element("Contents"); if (contents == null) continue; XElement str = contents.Element("Str"); if (str == null) continue; foreach (XElement run in str.Elements("Run")) { XAttribute linkAttr = run.Attribute("ownlink"); if (linkAttr == null) continue; // Run doesn't contain a link DomainObjectDTO linkObj; // skip links to missing footnotes - user will have to clean these up later. if (!domainObjectDtoRepository.TryGetValue(linkAttr.Value, out linkObj)) continue; XElement footnote = XElement.Parse(linkObj.Xml); if (footnote.Attribute("class").Value != "ScrFootnote") continue; // Link is not for a footnote if (footnote.Element("ParaContainingOrc") == null) { // ParaContainingOrc property is not present in the footnote, so it needs // to be added. XElement paraContainingOrcElm = XElement.Parse("<ParaContainingOrc><objsur guid=\"" + scrTxtPara.Guid + "\" t=\"r\" /></ParaContainingOrc>"); footnote.Add(paraContainingOrcElm); DataMigrationServices.UpdateDTO(domainObjectDtoRepository, linkObj, footnote.ToString()); } } } DataMigrationServices.IncrementVersionNumber(domainObjectDtoRepository); }
/// <summary> /// Verify that a given LexEntryType exists, and that IsProtected is set to true. /// </summary> private void VerifyEntryType(IDomainObjectDTORepository repoDto, string guid) { DomainObjectDTO dto; Assert.IsTrue(repoDto.TryGetValue(guid, out dto), String.Format("Check for known guid of LexEntryType ({0}).", m_mapGuidToName[guid])); var xeType = XElement.Parse(dto.Xml); Assert.IsNotNull(xeType); var xeProt = xeType.XPathSelectElement("IsProtected"); Assert.IsNotNull(xeProt, String.Format("IsProtected should exist ({0}).", m_mapGuidToName[guid])); var xaVal = xeProt.Attribute("val"); Assert.IsNotNull(xaVal, String.Format("IsProtected should have a val attribute ({0}).", m_mapGuidToName[guid])); Assert.AreEqual("true", xaVal.Value.ToLowerInvariant(), String.Format("IsProtected should be true ({0}).", m_mapGuidToName[guid])); }
public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) { DataMigrationServices.CheckVersionNumber(domainObjectDtoRepository, 7000056); IList<string> irregularlyInflectedFormVariantTypeSystemGuids = new List<string>() { LexEntryTypeTags.kguidLexTypIrregInflectionVar.ToString(), LexEntryTypeTags.kguidLexTypPluralVar.ToString(), LexEntryTypeTags.kguidLexTypPastVar.ToString() }; // first change the class of all the known systemGuids foreach (var systemGuid in irregularlyInflectedFormVariantTypeSystemGuids) { DomainObjectDTO dtoVariantType; // LT-13312 Note some projects may not have these guids. if (domainObjectDtoRepository.TryGetValue(systemGuid, out dtoVariantType)) { ChangeClassOfOwnerAndChildren(domainObjectDtoRepository, dtoVariantType, LexEntryTypeTags.kClassName, LexEntryInflTypeTags.kClassName); } } DataMigrationServices.IncrementVersionNumber(domainObjectDtoRepository); }
/// <summary> /// Remove <paramref name="goner"/> and everything it owns. /// Be sure to include removing goner from its optional owning property. /// </summary> internal static void RemoveIncludingOwnedObjects(IDomainObjectDTORepository dtoRepos, DomainObjectDTO goner, bool removeFromOwner) { DomainObjectDTO gonerActual; if (!dtoRepos.TryGetValue(goner.Guid, out gonerActual)) { return; // Not in repos. } if (removeFromOwner) { var ownerDto = dtoRepos.GetOwningDTO(goner); if (ownerDto != null) { var ownerElement = XElement.Parse(ownerDto.Xml); var ownObjSurElement = (from objSurNode in ownerElement.Descendants("objsur") where objSurNode.Attribute("t").Value == "o" && objSurNode.Attribute("guid").Value.ToLower() == goner.Guid.ToLower() select objSurNode).FirstOrDefault(); // Ought not be null, but play it safe. if (ownObjSurElement != null) { ownObjSurElement.Remove(); } if (!RemoveEmptyPropertyElements(dtoRepos, ownerDto, ownerElement)) { // No empty property elements removed, so we have to do the update. UpdateDTO(dtoRepos, ownerDto, ownerElement.ToString()); } } } foreach (var ownedDto in dtoRepos.GetDirectlyOwnedDTOs(goner.Guid)) { RemoveIncludingOwnedObjects(dtoRepos, ownedDto, false); } dtoRepos.Remove(goner); }
public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) { DataMigrationServices.CheckVersionNumber(domainObjectDtoRepository, 7000056); IList <string> irregularlyInflectedFormVariantTypeSystemGuids = new List <string>() { LexEntryTypeTags.kguidLexTypIrregInflectionVar.ToString(), LexEntryTypeTags.kguidLexTypPluralVar.ToString(), LexEntryTypeTags.kguidLexTypPastVar.ToString() }; // first change the class of all the known systemGuids foreach (var systemGuid in irregularlyInflectedFormVariantTypeSystemGuids) { DomainObjectDTO dtoVariantType; // LT-13312 Note some projects may not have these guids. if (domainObjectDtoRepository.TryGetValue(systemGuid, out dtoVariantType)) { ChangeClassOfOwnerAndChildren(domainObjectDtoRepository, dtoVariantType, LexEntryTypeTags.kClassName, LexEntryInflTypeTags.kClassName); } } DataMigrationServices.IncrementVersionNumber(domainObjectDtoRepository); }
/// <summary> /// Verify that the ComplexEntryTypes and VariantEntryTypes lists contain all of the /// standard LexEntryType objects, and that that they point only to valid LexEntryType /// objects. /// </summary> private void VerifyTypeLists(IDomainObjectDTORepository repoDto) { foreach (var dtoList in repoDto.AllInstancesWithSubclasses("CmPossibilityList")) { var xeList = XElement.Parse(dtoList.Xml); foreach (var objsur in xeList.XPathSelectElements("Possibilities/objsur")) { var xaGuid = objsur.Attribute("guid"); Assert.IsNotNull(xaGuid, "objsur elements should always have a guid attribute."); var guid = xaGuid.Value; string name; DomainObjectDTO dtoPoss; Assert.IsTrue(repoDto.TryGetValue(guid, out dtoPoss), "Possibility Lists should point to valid objects."); VerifySubpossibilities(repoDto, dtoPoss); } } }
private static void RemoveDanglingReferences( IDomainObjectDTORepository dtoRepos, IEnumerable<DomainObjectDTO> allDtos) { foreach (var currentDto in allDtos) { // Fetch the referred (regular reference or owning reference) to object guids. var referredToGuids = ExtractReferencedObjects(currentDto); // See if it is a dangling ref, where target object has been deleted. foreach (var targetGuid in referredToGuids) { DomainObjectDTO referencedDto; if (dtoRepos.TryGetValue(targetGuid, out referencedDto)) continue; // targetGuid is a dangling reference. // Remove the <objsur> element from referring object (kvp Key). // The <objsur> will have its 'guid' attribute set to 'targetGuid'. // This will work for owned as well as standard referenced objects. var targetGuidAsString = targetGuid.ToLower(); var referringDto = dtoRepos.GetDTO(currentDto.Guid); var referringElement = XElement.Parse(referringDto.Xml); var emptyPropElements = new List<XElement>(); foreach (var danglingRef in (referringElement.Descendants("objsur").Where( objSurrElement => objSurrElement.Attribute("guid").Value.ToLower() == targetGuidAsString)).ToList()) { var propElement = danglingRef.Parent; danglingRef.Remove(); if (!propElement.HasAttributes && !propElement.HasElements) emptyPropElements.Add(propElement); } foreach (var emptyPropElement in emptyPropElements) emptyPropElement.Remove(); // Remove now empty property element. // Reset the xml. referringDto.Xml = referringElement.ToString(); dtoRepos.Update(referringDto); } } }
/// <summary> /// Remove <paramref name="goner"/> and everything it owns. /// Be sure to include removing goner from its optional owning property. /// </summary> internal static void RemoveIncludingOwnedObjects(IDomainObjectDTORepository dtoRepos, DomainObjectDTO goner, bool removeFromOwner) { DomainObjectDTO gonerActual; if (!dtoRepos.TryGetValue(goner.Guid, out gonerActual)) return; // Not in repos. if (removeFromOwner) { var ownerDto = dtoRepos.GetOwningDTO(goner); if (ownerDto != null) { var ownerElement = XElement.Parse(ownerDto.Xml); var ownObjSurElement = (from objSurNode in ownerElement.Descendants("objsur") where objSurNode.Attribute("t").Value == "o" && objSurNode.Attribute("guid").Value.ToLower() == goner.Guid.ToLower() select objSurNode).FirstOrDefault(); // Ought not be null, but play it safe. if (ownObjSurElement != null) ownObjSurElement.Remove(); if (!RemoveEmptyPropertyElements(dtoRepos, ownerDto, ownerElement)) { // No empty property elements removed, so we have to do the update. UpdateDTO(dtoRepos, ownerDto, ownerElement.ToString()); } } } foreach (var ownedDto in dtoRepos.GetDirectlyOwnedDTOs(goner.Guid)) RemoveIncludingOwnedObjects(dtoRepos, ownedDto, false); dtoRepos.Remove(goner); }
private static void DeleteUnneededGoners(IDomainObjectDTORepository dtoRepos, IEnumerable<DomainObjectDTO> goners, ICollection<string> neededGoners) { // We have run out of memory during this data migration on large projects. (See // FWR-3849.) One possible reason is that we can make 15000+ copies of LangProject // as we slowly squeeze out the owning links to Annotations. So let's collect them // all up at once, and remove them with a single change to the LangProject dto. var dtoLangProject = dtoRepos.AllInstancesSansSubclasses("LangProject").FirstOrDefault(); if (dtoLangProject != null) { var xeLangProject = XElement.Parse(dtoLangProject.Xml); var cAnn = xeLangProject.Descendants("objsur"). Where(t => (t.Attribute("t") != null && t.Attribute("t").Value == "o")).Count(); if (cAnn > 0) { var gonersInLangProject = new List<DomainObjectDTO>(cAnn); foreach (var goner in goners) { DomainObjectDTO gonerActual; if (!dtoRepos.TryGetValue(goner.Guid, out gonerActual)) continue; // Not in repos. if (neededGoners.Contains(goner.Guid)) continue; // still need this in the repository. var ownerDto = dtoRepos.GetOwningDTO(goner); if (ownerDto != null && ownerDto.Guid == dtoLangProject.Guid) gonersInLangProject.Add(gonerActual); } if (gonersInLangProject.Count > 0) { DataMigrationServices.RemoveMultipleIncludingOwnedObjects(dtoRepos, gonersInLangProject, dtoLangProject); gonersInLangProject.Clear(); // We don't try removing those from goners because that operation may // involve a linear lookup in the list to find the object to remove. // And RemoveIncludingOwnedObjects() checks whether the goner still // exists before doing anything else. } } } // Remove old stuff. foreach (var goner in goners) { if (neededGoners.Contains(goner.Guid)) continue; DataMigrationServices.RemoveIncludingOwnedObjects(dtoRepos, goner, true); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Migrate data from 7000009 to 7000010. /// </summary> /// ------------------------------------------------------------------------------------ public void PerformMigration(IDomainObjectDTORepository dtoRepos) { DataMigrationServices.CheckVersionNumber(dtoRepos, 7000009); // The old objects to be removed go into 'goners'. // In this case, it is the annotation defn type objects. var goners = new List<DomainObjectDTO>((int) (dtoRepos.Count*0.80)); DomainObjectDTO dtoGoner; if (dtoRepos.TryGetValue(DataMigrationServices.kSegmentAnnDefnGuid, out dtoGoner)) goners.Add(dtoGoner); if (dtoRepos.TryGetValue(DataMigrationServices.kTwficAnnDefnGuid, out dtoGoner)) goners.Add(dtoGoner); if (dtoRepos.TryGetValue(DataMigrationServices.kPficAnnDefnGuid, out dtoGoner)) goners.Add(dtoGoner); if (dtoRepos.TryGetValue(DataMigrationServices.kFreeTransAnnDefnGuid, out dtoGoner)) goners.Add(dtoGoner); if (dtoRepos.TryGetValue(DataMigrationServices.kLitTransAnnDefnGuid, out dtoGoner)) goners.Add(dtoGoner); if (dtoRepos.TryGetValue(DataMigrationServices.kTextTagAnnDefnGuid, out dtoGoner)) goners.Add(dtoGoner); // Some old projects somehow didn't get this annotation type, so make all of these // dependent on actually existing. (See LT-11416.) if (dtoRepos.TryGetValue(DataMigrationServices.kDiscourseChartComponentAnnDefnGuid, out dtoGoner)) goners.Add(dtoGoner); // Don't delete it, since it owns two other type defns which are not part of this DM. //goners.Add(domainObjectDtoRepository.GetDTO(CmAnnotationDefnTags.kguidAnnNote.ToString())); // Gather up CmBaseAnnotations of interest. // Typically (if there are enough to be a possible problem, anyway) most of them are xfics. // Therefore the dictionaries which will get one entry per xfic are initialized to be large // enough to hold an item for each annotation. // This wastes a little memory, but repeatedly resizing the dictionaries can waste a LOT more, // as chunks of address space become unuseable. It also saves time. int annotationCount = dtoRepos.AllInstancesSansSubclasses("CmBaseAnnotation").Count(); var paraToOldSegments = new Dictionary<string, SortedList<int, byte[]>>(annotationCount/5); // Gather old segments that have duplicate BeginOffsets for a given paragraph. var paraToDuplicateOldSegments = new Dictionary<string, SortedList<int, List<byte[]>>>(); var paraToOldXfics = new Dictionary<string, SortedList<int, byte[]>>(/*annotationCount/24*/); // Gather old xfics that have duplicate BeginOffsets for a given paragraph. var paraToDuplicateOldXfics = new Dictionary<string, SortedList<int, List<byte[]>>>(); // Key is old ann guid. Value is old ann XElement. var oldCCAs = new Dictionary<string, byte[]>(annotationCount/5); // Key is old CCA ann guid. Value is the new CCA guid. var ccaGuidMap = new Dictionary<Guid, Guid>(annotationCount); // Keep track of xfics with inbound refs from Text tags and/or discourse, // which is used to help select among duplicates. var xficHasTextOrDiscourseBackReference = new Dictionary<string, int>(annotationCount/5); CollectBaseAnnotations(dtoRepos, goners, oldCCAs, ccaGuidMap, xficHasTextOrDiscourseBackReference, paraToDuplicateOldSegments, paraToOldSegments, paraToDuplicateOldXfics, paraToOldXfics); // Gather up CmIndirectAnnotations of interest. var freeTrans = new Dictionary<string, List<byte[]>>(annotationCount/3); var litTrans = new Dictionary<string, List<byte[]>>(); var notes = new Dictionary<string, List<byte[]>>(); var oldCCRows = new List<byte[]>(); var oldTextTags = new List<byte[]>(); CollectIndirectAnnotations(dtoRepos, goners, oldCCAs, ccaGuidMap, xficHasTextOrDiscourseBackReference, oldCCRows, oldTextTags, freeTrans, litTrans, notes); // Delete (right now, not later) any CCRs and any CCAs the CCRs reference, // which are not referenced by any DsConstChart (old Rows ref col prop). // Also, remove any immediately deleted CCRs and CCAs from the 'goners' // delayed deletion list, and the 'oldCCAs' and 'oldCCRows' lists. // We do this deletion/removal, so the duplicate selection // code that is called next won't have to worry about such clutter. DeleteImmediatelyAllUnlovedCCRs(dtoRepos, goners, xficHasTextOrDiscourseBackReference, oldCCRows, oldCCAs, ccaGuidMap); // Sort out duplicates. SelectFromDuplicates(dtoRepos, xficHasTextOrDiscourseBackReference, paraToOldXfics, paraToDuplicateOldXfics); paraToDuplicateOldSegments.Clear(); paraToDuplicateOldXfics.Clear(); paraToDuplicateOldSegments = null; paraToDuplicateOldXfics = null; // Look for any xfics that have multiple CCA backrefs. // If we find any, look through backrefs of CCAs and backrefs of // xfic.BeginObj to see which, if any, CCA is not in a chart BasedOn the right text. SortOutMultipleXficBackrefs(dtoRepos, xficHasTextOrDiscourseBackReference, oldCCAs, ccaGuidMap, oldCCRows, goners); // Feed 'halfBakedCcwgItems' into ProcessParagraphs (and thence, into the seg processor). // Then, the new kvp 'Values' can be finished (seg & twfic indices). // kvp Key is the orginal twfic/pfic element. // Kvp Value is a new ConstChartWordGroup that uses the xfic. var halfBakedCcwgItems = ProcessDiscourseData( dtoRepos, paraToOldSegments, oldCCRows, oldCCAs, ccaGuidMap); oldCCRows.Clear(); oldCCRows = null; // One reason for running out memory is adding to dtoRepos while in // ProcessParagraphs(). (See LT-11241.) So we'll delete all the goners that aren't // referenced in ProcessParagraphs(). Fortunately, it's fairly simple to find out // which those are. var neededGoners = new HashSet<string>(); foreach (var kvp in halfBakedCcwgItems) { var refs = GetAppliesToObjsurGuids(kvp.Key); if (refs == null || refs.Count == 0) continue; var guid = refs[0]; neededGoners.Add(guid); } DeleteUnneededGoners(dtoRepos, goners, neededGoners); if (neededGoners.Count == 0) goners.Clear(); neededGoners.Clear(); // Process each paragraph. ProcessParagraphs(dtoRepos, oldCCAs, halfBakedCcwgItems, paraToOldSegments, paraToOldXfics, ccaGuidMap, oldTextTags, freeTrans, litTrans, notes); oldCCAs.Clear(); halfBakedCcwgItems.Clear(); paraToOldSegments.Clear(); paraToOldXfics.Clear(); ccaGuidMap.Clear(); oldTextTags.Clear(); freeTrans.Clear(); litTrans.Clear(); notes.Clear(); oldCCAs = null; halfBakedCcwgItems = null; paraToOldSegments = null; paraToOldXfics = null; ccaGuidMap = null; oldTextTags = null; freeTrans = null; litTrans = null; notes = null; if (goners.Count > 0) { DeleteUnneededGoners(dtoRepos, goners, neededGoners); goners.Clear(); } // There may be zombies left from earlier DMs, // since they didn't do recursive deletions on a then zombie's owned objects. // This left additional zombies. // This won't affect regular users that come from FW 6.0, // as the original issue was fixed. // Nevertheless, given the drastic nature of this DM, // it's best to clean out any unexpected inbound refs to stuff that is going away, // rather than let FW crash, when trying to reconstitute zombies/dangling references. DataMigrationServices.Delint(dtoRepos); // LT-11593 Apparently somehow it is possible to have a wfic that doesn't belong // to a text that is referred to by a CCWG! One db had 9 chart cells that referred // to this type of wfic that has no other backreferences. At this point in the migration, // the offending wfic will have been deleted. Now we will delete the CCWG because it // will have Begin/EndAnalysisIndex = some guid instead of an integer! DeleteCcwgWithGuidIndex(dtoRepos); DataMigrationServices.IncrementVersionNumber(dtoRepos); }
private static DomainObjectDTO GetListDto(IDomainObjectDTORepository dtoRepos, XElement owningElem, string flidName) { var xPath = flidName + "/objsur"; var objsurElem = owningElem.XPathSelectElement(xPath); if (objsurElem == null) return null; var guid = objsurElem.Attribute("guid").Value; DomainObjectDTO dto; if(dtoRepos.TryGetValue(guid, out dto)) return dto; return null; }
private void VerifySubpossibilities(IDomainObjectDTORepository repoDto, DomainObjectDTO dtoPoss) { var xePoss = XElement.Parse(dtoPoss.Xml); foreach (var objsur in xePoss.XPathSelectElements("SubPossibilities/objsur")) { var xaGuid = objsur.Attribute("guid"); Assert.IsNotNull(xaGuid, "objsur elements should always have a guid attribute."); var guid = xaGuid.Value; string name; DomainObjectDTO dtoSub; Assert.IsTrue(repoDto.TryGetValue(guid, out dtoSub), "SubPossibility Lists should point to valid objects."); VerifySubpossibilities(repoDto, dtoSub); } }