private void Parse(IStText text, ProgressState progress) { progress.SetMilestone(ITextStrings.ksPreparingInterlinear1); progress.Breath(); m_ihvoPara = 0; m_hvoText = text.Hvo; m_cparas = text.ParagraphsOS.Count; #if DEBUG //TimeRecorder.End("setup"); //TimeRecorder.Begin("parse"); #endif progress.SetMilestone(ITextStrings.ksPreparingInterlinear2); progress.Breath(); // we only need to load our real database information once, since it's for all paragraphs. if (!m_fFinishedBuildAnalysisList) { BuildAnalysisList(progress); } progress.SetMilestone(ITextStrings.ksPreparingInterlinear3); progress.Breath(); Cache.PreloadIfMissing(text.ParagraphsOS.HvoArray, (int)StTxtPara.StTxtParaTags.kflidContents, 0, false); foreach (StTxtPara para in text.ParagraphsOS) { Setup(para); Parse(); m_ihvoPara++; //progress.Breath(); } #if DEBUG //TimeRecorder.End("parse"); //TimeRecorder.End("parse text"); #endif progress.SetMilestone(ITextStrings.ksPreparingInterlinear4); progress.Breath(); #if DEBUG //TimeRecorder.Begin("note parse times"); #endif // If we didn't have to make any dummy annotations, this text is sufficiently analyzed not to need // any. Therefore we can record a time when this was done, and won't have to run the parser on it // again until it gets modified. If we made dummy ones, they will get thrown away when the // program exits or the cache is cleared, so we need to reparse the text the next time we see it // in order to make a new set of dummy annotations to display. // Enhance JohnT: possibly we could record a time in the cache to avoid reparsing if we come back // to this text and have NOT modified it and the dummy annotations are still in memory. // Enhance JohnT: currently nothing ever makes real punctuation annotations. Therefore hardly any // text will ever be fully annotated (no dummy annotations). We may want to enhance so that // if the only dummy annotations in a text are punctuation, we make real punctuation annotations // so we can record a complete annotation timestamp. // But: currently we need to parse every text when first brought into memory, because that is // what makes the dummy TwficRealForm property values that let us get case right. Unless we change // that, the whole mechanism for tracking whether it is up to date in the database is irrelevant. IOleDbCommand odc = null; try { text.Cache.DatabaseAccessor.CreateCommand(out odc); if (!m_fMadeDummyAnnotations) { string sql2 = string.Format("declare @res nvarchar(4000);" + " exec NoteInterlinProcessTime {0}, {1}, @res OUTPUT; select @res", CmAnnotationDefn.ProcessTime(text.Cache).Hvo, text.Hvo); uint cbSpaceTaken; bool fMoreRows; bool fIsNull; byte[] rgbTemp = null; using (ArrayPtr rgchMarshalled = MarshalEx.ArrayToNative(4000, typeof(char))) { progress.Breath(); odc.ExecCommand(sql2, (int)SqlStmtType.knSqlStmtStoredProcedure); odc.GetRowset(0); // We need to update the cache if one or more CmBaseAnnotation objects were // created in LangProject_Annotations by the NoteInterlinProcessTime stored // procedure. odc.NextRow(out fMoreRows); odc.GetColValue(1, rgchMarshalled, rgchMarshalled.Size, out cbSpaceTaken, out fIsNull, 0); rgbTemp = (byte[])MarshalEx.NativeToArray(rgchMarshalled, (int)cbSpaceTaken, typeof(byte)); } char[] delim = { ',' }; string[] sVals = Encoding.Unicode.GetString(rgbTemp).Split(delim); List<int> newAnns = new List<int>(); for (int i = 0; i < sVals.Length; ++i) { if (sVals[i].Length != 0) { int hvo = Convert.ToInt32(sVals[i]); newAnns.Add(hvo); } } int[] newAnnotations = DbOps.ListToIntArray(newAnns); if (newAnnotations.Length != 0) { progress.Breath(); // update the cache. IVwCacheDa csda = text.Cache.MainCacheAccessor as IVwCacheDa; Debug.Assert(csda != null); int hvoObj = text.Cache.LangProject.Hvo; int ihvoLim = text.Cache.LangProject.AnnotationsOC.Count; csda.CacheReplace(hvoObj, (int)LangProject.LangProjectTags.kflidAnnotations, ihvoLim, ihvoLim, newAnnotations, newAnnotations.Length); } } } finally { DbOps.ShutdownODC(ref odc); progress.Breath(); } progress.SetMilestone(ITextStrings.ksPreparingInterlinear5); progress.Breath(); }
protected virtual void CleanupLeftoverRealAnnotations(ProgressState progress) { if (m_matcher != null) return; // we're just doing a partial parse, so keep all real annotations. Set<int> idsToDel = new Set<int>(); // Add to the document all the things we want to delete. // (For each paragraph we've parsed...) // Any existing annotations we haven't reused need to be done away with. // Instead of deleting unused twfics, we'll simply reserve them to be reused later. CmBaseAnnotation.ReserveAnnotations(m_cache, m_unusedTwficAnnotations, false); // AddIdsToDel(progress, ref idsToDel, m_unusedTwficAnnotations); AddIdsToDel(progress, idsToDel, m_unusedPunctuationAnnotations); AddIdsToDel(progress, idsToDel, m_unusedSegmentAnnotations); if (idsToDel.Count > 0) { if (progress is MilestoneProgressState) { MilestoneProgressState mp = progress as MilestoneProgressState; mp.AddMilestone(1); } Debug.WriteLine("Removing leftover annotations: " + CmObject.JoinIds(idsToDel.ToArray(), ",")); // Enhance JohnT: should we do something (delete or move?) about any freeform annotations // attached to these segments? For now they will become orphans... CmObject.DeleteObjects(idsToDel, Cache, VwClearInfoAction.kciaRemoveObjectInfoOnly); progress.SetMilestone(); progress.Breath(); } m_unusedTwficAnnotations.Clear(); m_unusedPunctuationAnnotations.Clear(); m_unusedSegmentAnnotations.Clear(); }
internal static List<int> ConcordParagraphs(FdoCache cache, int[] hvosStTxtPara, ProgressState progress, IMatcher matcher, ConcordanceControl.ConcordanceLines line) { using (ParagraphParser pp = new ParagraphParser(cache)) { // this will effectively clear ConcordanceWordforms, which seems overkill, but // since we are changing the occurrences on those wordforms, // and also possibly adding many new wordforms, we should just allow RecordLists that use // ConcordanceWordforms to reload the list. // (Enhance: is there any way we can make those lists be smart about when they need to reload, // rather than forcing them to?) (pp.m_wfi as WordformInventory).SuspendUpdatingConcordanceWordforms = true; pp.CreateDummyWordforms = true; pp.m_hvosStTxtPara = hvosStTxtPara; if (matcher != null) pp.m_matchingAnnotations = new List<int>(); ParagraphParser.ResetParseSessionDependentStaticData(); // Estimate the number of total number of milestones we'll set. // Enhance: we could construct a way to set percentage done based upon // number of texts and paragraphs in each text. if (progress is MilestoneProgressState) { MilestoneProgressState mp = progress as SIL.FieldWorks.Common.Controls.MilestoneProgressState; for (int i = 0; i < pp.m_hvosStTxtPara.Length; ++i) { mp.AddMilestone(1); } } // Preload all the paragraphs. cache.PreloadIfMissing(hvosStTxtPara, (int)StTxtPara.StTxtParaTags.kflidContents, 0, false); // Parse each text to load our paragraph and wordform segment annotations. int cPara = 0; using (SuppressSubTasks suppressor = new SuppressSubTasks(cache, true)) { foreach (IStTxtPara para in new FdoObjectSet<IStTxtPara>(cache, pp.m_hvosStTxtPara, false)) { ++cPara; pp.Parse(para, matcher, line); progress.SetMilestone(); progress.Breath(); if (pp.m_matchingAnnotations != null && pp.m_matchingAnnotations.Count >= ConcordanceControl.MaxConcordanceMatches()) { MessageBox.Show(String.Format(ITextStrings.ksShowingOnlyTheFirstXXXMatches, pp.m_matchingAnnotations.Count, cPara, pp.m_hvosStTxtPara.Length), ITextStrings.ksNotice, MessageBoxButtons.OK, MessageBoxIcon.Information); break; } } pp.CleanupLeftoverAnnotations(progress); } progress.SetMilestone(); progress.Breath(); (pp.m_wfi as WordformInventory).SuspendUpdatingConcordanceWordforms = false; return pp.m_matchingAnnotations; } }
/// <summary> /// Delete the underlying object. Note that this is deliberatly NOT virtual. Special delete /// behaviors should be implemented on DeleteObjectSideEffects. /// </summary> public void DeleteUnderlyingObject(ProgressState state) { Set<int> idsToDelete = new Set<int>(); FdoCache cache = m_cache; // BEFORE DeleteObjectSideEffects, which erases it! state.SetMilestone(Strings.ksGatheringInfo); state.Breath(); DeleteObjectSideEffects(idsToDelete, state); state.SetMilestone(Strings.ksActualDelete); DeleteObjects(idsToDelete, cache); }