예제 #1
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Verifies that the footnote marker was deleted from the specified back translation
		/// </summary>
		/// <param name="hvoPara">HVO of the paragraph that contains the footnote marker</param>
		/// <param name="guidFootnote">GUID of the deleted footnote</param>
		/// <param name="ws">The HVO of the back trans writing system to check</param>
		/// ------------------------------------------------------------------------------------
		private void VerifyRemovedFootnoteMarker(int hvoPara, Guid guidFootnote, int ws)
		{
			StTxtPara para = new StTxtPara(Cache, hvoPara);
			ICmTranslation trans = para.GetBT();
			if (trans == null)
				return; // no back translation exists to check
			ITsString tssBt = trans.Translation.GetAlternativeTss(ws);
			VerifyRemovedFootnoteMarker(guidFootnote, tssBt);
		}
예제 #2
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Removes the duplicate verse numbers in text.
		/// </summary>
		/// <param name="text">The text (either the remainder of the text following the
		/// paragraph where the insertion ocurred or in the next section)</param>
		/// <param name="iParaStart">The index of the para to start searching for dups.</param>
		/// <param name="inBackTrans">Indicates whether to search in back trans.</param>
		/// <param name="propTag">The flid (Contents or Translation)</param>
		/// <param name="wsAlt">The writing system, if a back trans multiString alt</param>
		/// <param name="chapterToRemove">The duplicate chapter number to remove.</param>
		/// <param name="removeUpToVerse">The last duplicate verse number to remove.</param>
		/// <returns><c>true</c> if all remaining duplicates have been removed; <c>false</c>
		/// if caller should re-call this method with the next section (or just give up)
		/// </returns>
		/// ------------------------------------------------------------------------------------
		private bool RemoveDuplicateVerseNumbersInText(IStText text, int iParaStart,
			bool inBackTrans, int propTag, int wsAlt, int chapterToRemove, int removeUpToVerse)
		{
			ITsString tss;
			int[] paraHvos = text.ParagraphsOS.HvoArray;
			for (int iPara = iParaStart; iPara < paraHvos.Length; iPara++)
			{
				// Get hvo and tss for this para or translation
				StTxtPara para = new StTxtPara(m_cache, paraHvos[iPara]);
				int hvoObj = 0;
				if (inBackTrans)
				{
					ICmTranslation trans = para.GetBT();
					if (trans == null)
						continue;
					hvoObj = trans.Hvo;
					tss = trans.Translation.GetAlternative(wsAlt).UnderlyingTsString;
				}
				else
				{
					hvoObj = para.Hvo;
					tss = para.Contents.UnderlyingTsString;
				}

				// Remove any duplicate verse number in this para or translation
				if (RemoveDuplicateVerseNumbersInPara(hvoObj, propTag, tss, wsAlt,
					chapterToRemove, removeUpToVerse, 0))
				{
					return true; // removal is complete
				}
			}
			return false; // removal isn't complete
		}
예제 #3
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Helper method:
		/// Verify the given copied paragraph, including footnotes and back translation, for
		/// any problems that the ChangeWatcher might cause.
		/// </summary>
		/// ------------------------------------------------------------------------------------
		private void VerifyCopiedPara(StTxtPara newPara)
		{
			int btWs = Cache.DefaultAnalWs;

			// Check the paragraph BT
			// para must have only only 1 translation, the BT
			Assert.AreEqual(1, newPara.TranslationsOC.Count);
			ICmTranslation paraTrans = newPara.GetBT();
			// BT alternate must have the original status
			Assert.AreEqual(BackTranslationStatus.Checked.ToString(),
				paraTrans.Status.GetAlternative(btWs));

			// Check the footnote BT
			Assert.AreEqual(1, m_genesis.FootnotesOS.Count);
			StFootnote footnote = (StFootnote)m_genesis.FootnotesOS[0];
			StTxtPara footnotePara = (StTxtPara)footnote.ParagraphsOS[0];
			// footnote must have only only 1 translation, the BT
			Assert.AreEqual(1, footnotePara.TranslationsOC.Count);
			ICmTranslation footnoteTrans = footnotePara.GetBT();
			// BT alternate must have the original status
			Assert.AreEqual(BackTranslationStatus.Finished.ToString(),
				footnoteTrans.Status.GetAlternative(btWs));
		}
예제 #4
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Adjust the back translation of footnotes to reference the newly-created guid in the
		/// archive.
		/// </summary>
		/// <param name="origGuid">guid for footnote in original book</param>
		/// <param name="newGuid">guid for footnote in archive</param>
		/// <param name="para">paragraph (potentially containing a translation)</param>
		/// ------------------------------------------------------------------------------------
		private void AdjustBtFootnoteInArchivedBook(Guid origGuid, Guid newGuid, StTxtPara para)
		{
			//TODO: TE- 5082 Duplicate code! Should call StTxtPara.UpdateOrcsInTranslations(), or common code
			ICmTranslation trans = para.GetBT();

			if (trans != null)
			{
				// Check the back translation for each writing system.
				foreach (ILgWritingSystem ws in m_cache.LangProject.AnalysisWssRC)
				{
					ITsString btTss = trans.Translation.GetAlternative(ws.Hvo).UnderlyingTsString;
					if (btTss.RunCount > 0)
					{
						// Scan through runs searching for a reference guid with the original guid.
						int cRuns = btTss.RunCount;
						TsRunInfo tri;
						ITsTextProps ttp;
						for (int iRun = 0; iRun < cRuns; iRun++)
						{
							Guid guid = StringUtils.GetGuidFromRun(btTss, iRun, out tri, out ttp);

							if (guid != Guid.Empty && guid == origGuid)
							{
								// Guid mapping back to orignal draft found. Update it.
								byte[] objData;
								objData = MiscUtils.GetObjData(newGuid,
									(byte)FwObjDataTypes.kodtNameGuidHot);
								ITsPropsBldr propsBldr;
								propsBldr = ttp.GetBldr();
								propsBldr.SetStrPropValueRgch(
									(int)FwTextPropType.ktptObjData,
									objData, objData.Length);
								ITsStrBldr btTssBldr = btTss.GetBldr();
								btTssBldr.SetProperties(tri.ichMin, tri.ichLim,
									propsBldr.GetTextProps());
								// Set the translation alt string to the new value
								// (but prevent side effects from ChangeWatchers)
								using (new IgnorePropChanged(m_cache, PropChangedHandling.SuppressChangeWatcher))
								{
									trans.Translation.SetAlternative(btTssBldr.GetString(), ws.Hvo);
								}
								break;
							}
						}
					}
				}
			}
		}
예제 #5
0
		public void ReplaceCurWithRev_ParaMissingInCurrent_WithBT()
		{
			// Build Current section (two paragraphs with verses 1, 3)
			IScrSection sectionCur = CreateSection(m_genesis, "My aching head!");
			StTxtPara para1Curr = m_scrInMemoryCache.AddParaToMockedSectionContent(sectionCur.Hvo, ScrStyleNames.NormalParagraph);
			m_scrInMemoryCache.AddRunToMockedPara(para1Curr, "1", ScrStyleNames.VerseNumber);
			m_scrInMemoryCache.AddRunToMockedPara(para1Curr, "verse one", Cache.DefaultVernWs);
			StTxtPara para3Curr = m_scrInMemoryCache.AddParaToMockedSectionContent(sectionCur.Hvo, ScrStyleNames.NormalParagraph);
			m_scrInMemoryCache.AddRunToMockedPara(para3Curr, "3", ScrStyleNames.VerseNumber);
			m_scrInMemoryCache.AddRunToMockedPara(para3Curr, "verse three", Cache.DefaultVernWs);
			sectionCur.AdjustReferences();

			// Build Revision section (three paragraphs - verses 1, 2, and 3)
			IScrSection sectionRev = CreateSection(m_genesisRevision, "My aching head!");
			// this first para matches the current
			StTxtPara para1Rev = m_scrInMemoryCache.AddParaToMockedSectionContent(sectionRev.Hvo, ScrStyleNames.NormalParagraph);
			m_scrInMemoryCache.AddRunToMockedPara(para1Rev, "1", ScrStyleNames.VerseNumber);
			m_scrInMemoryCache.AddRunToMockedPara(para1Rev, "verse one", Cache.DefaultVernWs);
			// this second para is missing in the current
			StTxtPara para2Rev = m_scrInMemoryCache.AddParaToMockedSectionContent(sectionRev.Hvo, ScrStyleNames.NormalParagraph);
			m_scrInMemoryCache.AddRunToMockedPara(para2Rev, "2", ScrStyleNames.VerseNumber);
			m_scrInMemoryCache.AddRunToMockedPara(para2Rev, "verse two", Cache.DefaultVernWs);
			// this third para matches the current
			StTxtPara para3Rev = m_scrInMemoryCache.AddParaToMockedSectionContent(sectionRev.Hvo, ScrStyleNames.NormalParagraph);
			m_scrInMemoryCache.AddRunToMockedPara(para3Rev, "3", ScrStyleNames.VerseNumber);
			m_scrInMemoryCache.AddRunToMockedPara(para3Rev, "verse three", Cache.DefaultVernWs);

			// The second para includes a footnote
			StFootnote footnote2Rev = m_scrInMemoryCache.AddFootnote(m_genesisRevision, para2Rev, 1, "New footnote text");

			// Add back translation to the second revision paragraph, and its status
			int btWs = Cache.DefaultAnalWs;
			ICmTranslation transPara2Rev = m_inMemoryCache.AddBtToMockedParagraph(para2Rev, btWs);
			m_inMemoryCache.AddRunToMockedTrans(transPara2Rev, btWs, "BT of verse two", null);
			transPara2Rev.Status.SetAlternative(BackTranslationStatus.Finished.ToString(), btWs);

			// Add back translation of footnote
			ICmTranslation transFootnote = m_scrInMemoryCache.AddFootnoteORCtoTrans(transPara2Rev, 2, btWs,
					footnote2Rev, "BT of footnote");
			transFootnote.Status.SetAlternative(BackTranslationStatus.Checked.ToString(), btWs);
			sectionRev.AdjustReferences();

			// Set up the Scripture ChangeWatcher
			ScriptureChangeWatcher.Create(Cache);

			// Detect differences
			m_bookMerger.DetectDifferences(null); // find the diffs for Genesis
			Assert.AreEqual(1, m_bookMerger.Differences.Count);

			// Get the first difference, verify it
			Difference diff = m_bookMerger.Differences.MoveFirst();
			Assert.AreEqual(DifferenceType.ParagraphMissingInCurrent, diff.DiffType);
			Assert.AreEqual(01001002, diff.RefStart);

			//do a ReplaceCurrentWithRevision to simulate clicking the "revert to old" button
			m_bookMerger.ReplaceCurrentWithRevision(diff);
			// we expect this to insert the second para from the revision, and it's back translation

			// Confirm that the vernacular paragraph is restored correctly.
			Assert.AreEqual(3, sectionCur.ContentOA.ParagraphsOS.Count);
			StTxtPara para2Curr = new StTxtPara(Cache, sectionCur.ContentOA.ParagraphsOS[1].Hvo);
			Assert.AreEqual(ScrStyleNames.NormalParagraph, para2Curr.StyleRules.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle));
			Assert.AreEqual("2" + StringUtils.kchObject + "verse two", para2Curr.Contents.Text);
			ITsString tssNewParaContents = para2Curr.Contents.UnderlyingTsString;
			Assert.AreEqual(3, tssNewParaContents.RunCount);
			AssertEx.RunIsCorrect(tssNewParaContents, 0, "2", ScrStyleNames.VerseNumber, Cache.DefaultVernWs, true);
			// Run #1 is ORC for footnote, checked below...
			AssertEx.RunIsCorrect(tssNewParaContents, 2, "verse two", null, Cache.DefaultVernWs, true);

			StFootnote footnoteNew = (StFootnote)m_genesis.FootnotesOS.FirstItem;
			VerifyFootnote(footnoteNew, para2Curr, 1);

			// Confirm that the paragraph's back translation is restored correctly.
			ICmTranslation newPara2trans = para2Curr.GetBT();
			Assert.IsNotNull(newPara2trans, "Second paragraph did not have translation restored from rev");
			ITsString tssNewBtParaContents = newPara2trans.Translation.GetAlternativeTss(btWs);

			Assert.AreEqual("BT" + StringUtils.kchObject + " of verse two", tssNewBtParaContents.Text);
			Assert.AreEqual(3, tssNewBtParaContents.RunCount);
			AssertEx.RunIsCorrect(tssNewBtParaContents, 0, "BT", null, btWs);
			// Run #1 is ORC for footnote, checked below...
			AssertEx.RunIsCorrect(tssNewBtParaContents, 2, " of verse two", null, btWs);
			StTxtParaTests.VerifyBtFootnote(footnoteNew, para2Curr, btWs, 2);
			// BT alternate must have the original status
			Assert.AreEqual(BackTranslationStatus.Finished.ToString(),
				newPara2trans.Status.GetAlternative(btWs));

			// Confirm that the footnote's back translation is restored correctly
			ICmTranslation newFootnoteTrans = ((StTxtPara)footnoteNew.ParagraphsOS[0]).GetBT();
			Assert.IsNotNull(newFootnoteTrans, "Footnote paragraph did not have translation restored from rev");
			Assert.AreEqual("BT of footnote",
					newFootnoteTrans.Translation.GetAlternativeTss(btWs).Text);
			// BT alternate must have the original status
			Assert.AreEqual(BackTranslationStatus.Checked.ToString(),
					newFootnoteTrans.Status.GetAlternative(btWs));

			Assert.AreEqual(0, m_bookMerger.Differences.Count);

			// Recheck that Current is now identical to Revision
			m_bookMerger.DetectDifferences_ReCheck();
			Assert.AreEqual(0, m_bookMerger.Differences.Count);
		}
예제 #6
0
		public static void UpdateMainTransFromSegmented(StTxtPara para, int[] wss)
		{
			if (!para.IsValidObject())
				return; // in merge, paragraph may be modified then deleted.
			FdoCache cache = para.Cache;
			BtConverter.EnsureMainParaSegments(para, wss[0]);
			ISilDataAccess sda = cache.MainCacheAccessor;
			List<int> segments = para.Segments;
			int kflidFT = StTxtPara.SegmentFreeTranslationFlid(cache);
			ITsString tssContents = para.Contents.UnderlyingTsString;
			IScripture scr = para.Cache.LangProject.TranslatedScriptureOA;
			ICmTranslation originalBT = para.GetBT(); // Can be null
			string sUnfinished = BackTranslationStatus.Unfinished.ToString();
			foreach (int ws in wss)
			{
				ITsStrBldr bldr = TsStrBldrClass.Create();
				bool wantNextSpace = false; // suppresses space before the first thing we add.
				bool haveBtText = false; // Text that isn't segment label text
				foreach (int hvoSeg in segments)
				{
					// If it's a label, insert it directly. Suppress following space.
					int beginOffset = sda.get_IntProp(hvoSeg, (int) CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginOffset);
					int endOffset = sda.get_IntProp(hvoSeg, (int) CmBaseAnnotation.CmBaseAnnotationTags.kflidEndOffset);
					ITsString tssFt;
					// Whether we want to insert a space before the current segment is determined by the previous one.
					// Save that value so we can set wantSpace appropriately for the following one.
					bool wantSpace = wantNextSpace;
					if (SegmentBreaker.HasLabelText(tssContents, beginOffset, endOffset))
					{
						tssFt = (new CmBaseAnnotation(cache, hvoSeg)).TextAnnotated;
						tssFt = scr.ConvertCVNumbersInStringForBT(CorrectFootnotes(tssFt), ws);
						wantNextSpace = false;
					}
					else
					{
						int hvoFt = sda.get_ObjectProp(hvoSeg, kflidFT);
						tssFt = sda.get_MultiStringAlt(hvoFt, (int) CmAnnotation.CmAnnotationTags.kflidComment, ws);
						haveBtText |= (tssFt.Length > 0);
						wantNextSpace = EndsWithNonSpace(tssFt);
					}
					if (tssFt.Length > 0)
					{
						if (wantSpace)
						{
							// The preceding segment should typically be followed by a space.
							if (!StartsWithSpaceOrOrc(tssFt))
								bldr.Replace(bldr.Length, bldr.Length, " ", null);
						}
						bldr.ReplaceTsString(bldr.Length, bldr.Length, tssFt);
					}
				}

				// If the back translation doesn't have text, we don't want to create verse
				// segment labels. This prevents the problem where the book thinks it has a
				// back translation because of automatically generated verse labels (TE-8283).
				if (!haveBtText)
				{
					// This check might not be needed, but it shouldn't hurt anything.
					if (originalBT != null)
					{
						if (originalBT.Translation.GetAlternative(ws).Length > 0)
						{
							string origStatus = originalBT.Status.GetAlternative(ws);
							if (!String.IsNullOrEmpty(origStatus) && origStatus != sUnfinished)
								originalBT.Status.SetAlternative(sUnfinished, ws);
						}
					}
					continue;
				}

				ITsString newFt = bldr.GetString();
				ICmTranslation trans;
				if (newFt.Length == 0)
				{
					trans = para.GetBT();
					if (trans == null)
						return; // don't bother creating one to store an empty translation!
				}
				else
				{
					trans = para.GetOrCreateBT();

				}
				// Don't write unless it changed...PropChanged can be expensive.
				if (!trans.Translation.GetAlternative(ws).UnderlyingTsString.Equals(newFt))
				{
					trans.Translation.SetAlternative(newFt, ws);
					trans.Status.SetAlternative(sUnfinished, ws);
				}
			}
		}
예제 #7
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Helper method  verifies that the copy was sufficiently "deep":
		/// copied paragraphs are different objects, and that owner and owned objects
		/// are different.
		/// </summary>
		/// <param name="srcPara">The para rev.</param>
		/// <param name="newPara">The new para.</param>
		/// ------------------------------------------------------------------------------------
		private static void VerifyParagraphsAreDifferentObjects(StTxtPara srcPara, StTxtPara newPara)
		{
			Assert.AreNotEqual(srcPara.Hvo, newPara.Hvo);
			// owned by different StTexts
			Assert.AreNotEqual(srcPara.OwnerHVO, newPara.OwnerHVO);
			// owning different back translations
			Assert.AreNotEqual(srcPara.GetBT().Hvo, newPara.GetBT().Hvo);
		}
예제 #8
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Helper method:
		/// Verify the given copied paragraph, including footnotes and back translation,
		/// plus any other fields deemed necessary.
		/// </summary>
		/// ------------------------------------------------------------------------------------
		private void VerifyCopiedPara(StTxtPara newPara)
		{
			// Verify the para StyleRules
			Assert.AreEqual("Line 1", newPara.StyleRules.GetStrPropValue((int)FwTextPropType.ktptNamedStyle));

			// Verify the para Contents
			Assert.AreEqual("11This" + StringUtils.kchObject + " is" + StringUtils.kchObject + " the previous version of the text.",
				newPara.Contents.Text);
			ITsString tssNewParaContents = newPara.Contents.UnderlyingTsString;
			Assert.AreEqual(7, tssNewParaContents.RunCount);
			AssertEx.RunIsCorrect(tssNewParaContents, 0, "1", "CharacterStyle1", Cache.DefaultVernWs, true);
			AssertEx.RunIsCorrect(tssNewParaContents, 1, "1", "CharacterStyle2", Cache.DefaultVernWs, true);
			AssertEx.RunIsCorrect(tssNewParaContents, 2, "This", null, Cache.DefaultVernWs, true);
			// Run #3 is ORC for footnote, checked below...
			AssertEx.RunIsCorrect(tssNewParaContents, 4, " is", null, Cache.DefaultVernWs, true);
			// Run #5 is ORC for footnote, checked below...
			AssertEx.RunIsCorrect(tssNewParaContents, 6, " the previous version of the text.", null, Cache.DefaultVernWs, true);

			// note: At this point, having done the Copyxx() but not CreateOwnedObjects(),
			//  the ORCs still refer to footnote objects owned by m_archivedText...
			StFootnote footnote1 = (StFootnote)m_archivedFootnotesOS.FirstItem;
			VerifyFootnote(footnote1, newPara, 6);
			Assert.AreEqual("Footnote1", ((StTxtPara)footnote1.ParagraphsOS[0]).Contents.Text);
			StFootnote footnote2 = (StFootnote)m_archivedFootnotesOS[1];
			VerifyFootnote(footnote2, newPara, 10);
			Assert.AreEqual("Footnote2", ((StTxtPara)footnote2.ParagraphsOS[0]).Contents.Text);
			// ...thus the footnotes are not yet in m_currentFootnotesOS.
			Assert.AreEqual(0, m_currentFootnotesOS.Count);

			// Verify the para translations
			Assert.AreEqual(1, newPara.TranslationsOC.Count); //only 1 translation, the BT
			ICmTranslation paraTrans = newPara.GetBT();
			// verify each alternate translation
			int[] wsBt = new int[] { InMemoryFdoCache.s_wsHvos.En, InMemoryFdoCache.s_wsHvos.De };
			foreach (int ws in wsBt)
			{
				ITsString tssBtParaContents = paraTrans.Translation.GetAlternativeTss(ws);
				Assert.AreEqual("BT" + StringUtils.kchObject + " of" + StringUtils.kchObject +
					" test paragraph" + ws.ToString(), tssBtParaContents.Text);
				Assert.AreEqual(5, tssBtParaContents.RunCount);
				// could check every run too, but we'll skip that
				Assert.AreEqual(BackTranslationStatus.Finished.ToString(),
					paraTrans.Status.GetAlternative(ws));
			}

			// Verify the footnote translations, their ORCs, and their status
			foreach (int ws in wsBt)
			{
				VerifyBtFootnote(footnote1, newPara, ws, 2);
				ICmTranslation footnoteTrans = ((StTxtPara)footnote1.ParagraphsOS[0]).GetBT();
				Assert.AreEqual("BT of footnote1 " + ws.ToString(),
					footnoteTrans.Translation.GetAlternativeTss(ws).Text);
				Assert.AreEqual(BackTranslationStatus.Checked.ToString(),
					footnoteTrans.Status.GetAlternative(ws));

				VerifyBtFootnote(footnote2, newPara, ws, 6);
				footnoteTrans = ((StTxtPara)footnote2.ParagraphsOS[0]).GetBT();
				Assert.AreEqual("BT of footnote2 " + ws.ToString(),
					footnoteTrans.Translation.GetAlternativeTss(ws).Text);
				Assert.AreEqual(BackTranslationStatus.Finished.ToString(),
					footnoteTrans.Status.GetAlternative(ws));
			}
		}
예제 #9
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Gets the text representation of the back translations for a footnote paragraph.
		/// </summary>
		/// <param name="footnotePara">The footnote paragraph.</param>
		/// <returns>
		/// text representation of all of the back translations for the footnote paragraph
		/// </returns>
		/// ------------------------------------------------------------------------------------
		private string GetTextRepresentationOfTrans(StTxtPara footnotePara)
		{
			string transRepresentation = string.Empty;
			CmTranslation trans = (CmTranslation)footnotePara.GetBT();
			if (trans == null)
				return transRepresentation;

			List<int> transWs = m_cache.GetUsedScriptureTransWsForPara(footnotePara.Hvo);

			foreach (int ws in transWs)
			{
				ITsString tss = trans.Translation.GetAlternativeTss(ws);
				if (tss != null && tss.Length > 0)
				{
					LgWritingSystem lgws = new LgWritingSystem(m_cache, ws);
					transRepresentation += "<TRANS WS='" + lgws.ICULocale + "'>";
					transRepresentation += GetTextRepresentationOfTsString(tss);
					transRepresentation += "</TRANS>";
				}
			}

			return transRepresentation;
		}