/// <summary> /// Adds a new wordform annotation (occurrence) to this wordform. /// </summary> /// <param name="hvoNewCba"></param> public bool TryAddOccurrence(int hvoNewCba) { int[] occurrences = m_cache.GetVectorProperty(this.Hvo, OccurrencesFlid(Cache), true); List<int> occurrencesList = new List<int>(occurrences); // lookup the occurrence to see if we already have it. (we don't want to add it twice). if (occurrencesList.IndexOf(hvoNewCba) != -1) return false; WfiWordform.AddDummyAnnotation(Cache, this.Hvo, hvoNewCba); // insert at the end. CacheReplaceOneUndoAction cacheReplaceOccurrenceAction = new CacheReplaceOneUndoAction(Cache, this.Hvo, OccurrencesFlid(Cache), occurrences.Length, occurrences.Length, new int[] { hvoNewCba }); cacheReplaceOccurrenceAction.DoIt(); return true; }
/// <summary> /// Find a dummy segment wordform annotation, and replace with a real annotation it in the cache. /// </summary> /// <param name="cache"></param> /// <param name="hvoOldAnnotation"></param> /// <param name="hvoNewAnnotation"></param> /// <returns>if nonzero, this will be inserted in place of the old one. /// if zero, we'll simply delete the old one.</returns> internal static void CacheReplaceTWFICAnnotation(FdoCache cache, int hvoOldAnnotation, int hvoNewAnnotation) { int ktagSegmentForms = CmBaseAnnotation.SegmentFormsFlid(cache); int kflidOccurrences = WfiWordform.OccurrencesFlid(cache); ISilDataAccess sda = cache.MainCacheAccessor; int hvoParaSeg = 0; int iParaSeg = -1; bool fIsFirstTwfic = false; int iSegForm = StTxtPara.TwficSegmentLocation(cache, hvoOldAnnotation, out hvoParaSeg, out iParaSeg, out fIsFirstTwfic); IVwCacheDa cda = cache.VwCacheDaAccessor; int[] newItems = hvoNewAnnotation != 0 ? new int[] { hvoNewAnnotation } : new int[0]; if (hvoParaSeg != 0 && iSegForm >= 0) { CacheReplaceOneUndoAction cacheReplaceSegmentFormAction = new CacheReplaceOneUndoAction(cache, hvoParaSeg, ktagSegmentForms, iSegForm, iSegForm + 1, newItems); cacheReplaceSegmentFormAction.DoIt(); if (cache.ActionHandlerAccessor != null) { cache.ActionHandlerAccessor.AddAction(cacheReplaceSegmentFormAction); } } int hvoOldWordform = 0; if (WfiWordform.TryGetWfiWordformFromInstanceOf(cache, hvoOldAnnotation, out hvoOldWordform)) { // replace the dummy annotation on its wordform, if we haven't already. List<int> dummyAnnotations = new List<int>(cache.GetVectorProperty(hvoOldWordform, kflidOccurrences, true)); int iAnn = dummyAnnotations.IndexOf(hvoOldAnnotation); if (iAnn >= 0) { CacheReplaceOneUndoAction cacheReplaceOccurrenceAction = new CacheReplaceOneUndoAction(cache, hvoOldWordform, kflidOccurrences, iAnn, iAnn + 1, newItems); cacheReplaceOccurrenceAction.DoIt(); if (cache.ActionHandlerAccessor != null) { cache.ActionHandlerAccessor.AddAction(cacheReplaceOccurrenceAction); } } } // try converting the owning segment to real, if we're converting the twfic to real. if (hvoOldAnnotation != 0 && hvoNewAnnotation != 0 && cache.IsDummyObject(hvoOldAnnotation) && !cache.IsDummyObject(hvoNewAnnotation) && cache.IsDummyObject(hvoParaSeg)) { hvoParaSeg = CmBaseAnnotation.ConvertBaseAnnotationToReal(cache, hvoParaSeg).Hvo; } }
/// <summary> /// Updates ConcordanceWordform if it's in the cache. /// Enhance: We could refactor this to call a more generic FdoCache.TryUpdatingVector(). /// </summary> /// <param name="fdoCache"></param> /// <param name="hvoOldWordform">if 0, we'll insert hvoNewWordform at the end of the list.</param> /// <param name="hvoNewWordform">if 0, we'll delete hvoOldWordform from the list.</param> /// <returns>true, if it updated the vector, false if it didn't.</returns> internal static bool TryUpdatingConcordanceWordforms(FdoCache fdoCache, int hvoOldWordform, int hvoNewWordform) { ISilDataAccess sda = fdoCache.MainCacheAccessor; IVwCacheDa cda = fdoCache.VwCacheDaAccessor; // If WFI has ConcordanceWordforms property, replace hvoOldWordform with hvoNewWordform in it. int kflidConcordanceWordforms = WordformInventory.ConcordanceWordformsFlid(fdoCache); int hvoWfi = fdoCache.LangProject.WordformInventoryOAHvo; if (sda.get_IsPropInCache(hvoWfi, kflidConcordanceWordforms, (int)CellarModuleDefns.kcptReferenceSequence, 0)) { List<int> wordforms = new List<int>(fdoCache.GetVectorProperty(hvoWfi, kflidConcordanceWordforms, true)); // if wordforms.Count == 0, we must be in a context that has affected the wordforms, // but doesn't want to take direct responsibility for maintaining this list. if (wordforms.Count == 0) { return false; } int ihvoWfNew = wordforms.IndexOf(hvoNewWordform); Debug.Assert(ihvoWfNew == -1, "We are trying to insert a new wordform, but it's already in the concordance."); int[] newItems = ihvoWfNew == -1 && hvoNewWordform != 0 ? new int[] { hvoNewWordform } : new int[0]; CacheReplaceOneUndoAction cacheReplaceOccurrenceAction; if (hvoOldWordform != 0) { // we are trying replacing an existing wordform in the ConcordanceWordforms. int ihvoWf = wordforms.IndexOf(hvoOldWordform); Debug.Assert(ihvoWf != -1, "We are trying to remove an old wordform, but it's not in the concordance."); if (ihvoWf >= 0) { cacheReplaceOccurrenceAction = new CacheReplaceOneUndoAction(fdoCache, hvoWfi, kflidConcordanceWordforms, ihvoWf, ihvoWf + 1, newItems); cacheReplaceOccurrenceAction.DoIt(); return true; } return false; } else if (ihvoWfNew == -1 && hvoNewWordform != 0) { // we are inserting a new wordform in ConcordanceWordforms. add it to the end of the list. cacheReplaceOccurrenceAction = new CacheReplaceOneUndoAction(fdoCache, hvoWfi, kflidConcordanceWordforms, wordforms.Count, wordforms.Count, newItems); cacheReplaceOccurrenceAction.DoIt(); return true; } } return false; }
/// <summary> /// Find a dummy paragraph segment annotation and replace it with a real annotation in the cache. /// </summary> /// <param name="cache"></param> /// <param name="hvoOldAnnotation"></param> /// <param name="hvoNewAnnotation">if nonzero, this will be inserted in place of the old one. /// if zero, we'll simply delete the old one.</param> internal static void CacheReplaceTextSegmentAnnotation(FdoCache cache, int hvoOldAnnotation, int hvoNewAnnotation) { int kflidParaSegments = StTxtPara.SegmentsFlid(cache); int ktagSegmentForms = CmBaseAnnotation.SegmentFormsFlid(cache); ISilDataAccess sda = cache.MainCacheAccessor; IVwCacheDa cda = cache.VwCacheDaAccessor; // find the paraSegment for the old annotation int hvoPara = sda.get_ObjectProp(hvoOldAnnotation, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject); List<int> paraSegments = new List<int>(cache.GetVectorProperty(hvoPara, kflidParaSegments, true)); int iParaSeg = paraSegments.IndexOf(hvoOldAnnotation); Debug.Assert(iParaSeg != -1); if (iParaSeg >= 0) { int[] segmentForms = cache.GetVectorProperty(hvoOldAnnotation, ktagSegmentForms, true); if (hvoNewAnnotation != 0) { // first, transfer the old annotation's WordformSegments vector. cda.CacheVecProp(hvoNewAnnotation, ktagSegmentForms, segmentForms, segmentForms.Length); } int[] newItems = hvoNewAnnotation != 0 ? new int[] { hvoNewAnnotation } : new int[0]; // now, replace the old paraSegment with the new. CacheReplaceOneUndoAction cacheReplaceParaSegmentAction = new CacheReplaceOneUndoAction( cache, hvoPara, kflidParaSegments, iParaSeg, iParaSeg + 1, newItems); cacheReplaceParaSegmentAction.DoIt(); if (cache.ActionHandlerAccessor != null) { cache.ActionHandlerAccessor.AddAction(cacheReplaceParaSegmentAction); } } }
/// <summary> /// Take a twfic annotation and merge it with the following twfic annotation, creating a new /// annotation to replace those two twfics. Also deletes any unreferenced wordforms as a result of /// the merge. /// </summary> /// <param name="hvoStartingAnnotation">segmentForm twfic annotation from which to merge and replace /// with the next twfic annotation. </param> /// <returns>the resulting merged (real) annotation form.</returns> /// <param name="hvoParasInView">the paragraphs used in the current display</param> public ICmBaseAnnotation MergeAdjacentSegmentForms(int hvoStartingAnnotation, int[] hvoParasInView) { // 1) Merge the current annotation with next twfic. int hvoSeg; int iSegForm; ICmBaseAnnotation currentAnnotation; ICmBaseAnnotation nextAnnotation; int hvoOldWordform1; int hvoOldWordform2; GetAdjacentWficInfo(hvoStartingAnnotation, out hvoSeg, out iSegForm, out currentAnnotation, out nextAnnotation, out hvoOldWordform1, out hvoOldWordform2); // Create a new wordform for this annotation. ITsString tssOldPhrase = this.Contents.UnderlyingTsString.GetSubstring( currentAnnotation.BeginOffset, currentAnnotation.EndOffset); ITsString tssNewPhrase = this.Contents.UnderlyingTsString.GetSubstring( currentAnnotation.BeginOffset, nextAnnotation.EndOffset); int hvoDummyWff = WfiWordform.FindOrCreateWordform(Cache, tssNewPhrase, false); // Create a new CmBaseAnnotation with merged field information. // set the analysis level for the next annotation to be the new wordform. int hvoNewAnn = CmBaseAnnotation.CreateDummyAnnotation(Cache, currentAnnotation.BeginObjectRAHvo, currentAnnotation.AnnotationTypeRAHvo, currentAnnotation.BeginOffset, nextAnnotation.EndOffset, hvoDummyWff); WfiWordform dummyWff = WfiWordform.CreateFromDBObject(Cache, hvoDummyWff) as WfiWordform; // Add the occurrence before we convert to real, so that our prop changes will have enough // information for listeners to update their lists. dummyWff.TryAddOccurrence(hvoNewAnn); ICmBaseAnnotation newAnnotation = CmObject.ConvertDummyToReal(Cache, hvoNewAnn) as ICmBaseAnnotation; CacheReplaceOneUndoAction cacheReplaceSegmentsFormAction = new CacheReplaceOneUndoAction(Cache, hvoSeg, CmBaseAnnotation.SegmentFormsFlid(Cache), iSegForm, iSegForm, new int[] { newAnnotation.Hvo }); cacheReplaceSegmentsFormAction.DoIt(); if (Cache.ActionHandlerAccessor != null) { Cache.ActionHandlerAccessor.AddAction(cacheReplaceSegmentsFormAction); } // Remove the two annotations we just replaced. // Enhance: make CmBaseAnnotation.DeleteUnderlyingObject add to annotation orphanage. currentAnnotation.DeleteUnderlyingObject(); // side-effects will remove annotation from paragraph SegForms. nextAnnotation.DeleteUnderlyingObject(); // See if we can remove any wordforms that are no longer refereneced by annotations/analyses. Set<int> delObjIds; TryDeleteWordforms(Cache, new int[] { hvoOldWordform1, hvoOldWordform2 }, hvoParasInView, out delObjIds); return newAnnotation; }
/// <summary> /// Make one, and do the action (with notification). /// </summary> public static void SetItUp(FdoCache cache, int hvo, int flid, int ihvoMin, int ihvoLim, int[] newValues) { CacheReplaceOneUndoAction action = new CacheReplaceOneUndoAction(cache, hvo, flid, ihvoMin, ihvoLim,newValues); action.DoIt(); }
/// <summary> /// Breaks the given (phrase-wordform) annotation to its basic wordforms. /// </summary> /// <param name="hvoCbaPhrase"></param> /// <param name="hvoParasInView">the paragraphs in the view doing the break phrase operation</param> /// <returns>ids of the new wordforms</returns> public List<int> BreakPhraseAnnotation(int hvoCbaPhrase, int[] hvoParasInView) { List<int> segForms; ICmBaseAnnotation phraseAnnotation = CmBaseAnnotation.CreateFromDBObject(Cache, hvoCbaPhrase); int phraseBeginOffset = phraseAnnotation.BeginOffset; int phraseEndOffset = phraseAnnotation.EndOffset; segForms = CollectSegmentForms(phraseBeginOffset, phraseEndOffset, false); StTxtPara.TwficInfo phraseInfo = new StTxtPara.TwficInfo(Cache, hvoCbaPhrase); int iSegForm = phraseInfo.SegmentFormIndex; int hvoParaSeg = phraseInfo.SegmentHvo; IVwCacheDa cda = Cache.VwCacheDaAccessor; ISilDataAccess sda = Cache.MainCacheAccessor; // convert dummy segForms to real ones. // This conversion is currently important to do before we exit BreakPhraseAnnotation because if we try to // convert a dummy annotation that references a dummy wordform, that dummy wordform // may be removed from the WordformInventory by DeleteUnderlyingObject()->OnChangedWordformsOC below. List<int> realSegForms = new List<int>(segForms.Count); foreach (int hvoSegForm in segForms) { int hvoNewWordform; WfiWordform.TryGetWfiWordformFromInstanceOf(Cache, hvoSegForm, out hvoNewWordform); if (hvoNewWordform != 0) { // This allows it to be converted to real, by specifying its owner and owning flid. WfiWordform.AddDummyAnnotation(Cache, hvoNewWordform, hvoSegForm); ICmBaseAnnotation realSegForm = CmObject.ConvertDummyToReal(Cache, hvoSegForm) as ICmBaseAnnotation; realSegForms.Add(realSegForm.Hvo); WfiWordform newWordform = WfiWordform.CreateFromDBObject(Cache, hvoNewWordform) as WfiWordform; // now add this occurrence to the wordform. newWordform.TryAddOccurrence(realSegForm.Hvo); } else { realSegForms.Add(hvoSegForm); // punctuation does not need to be real. } } // insert new forms. CacheReplaceOneUndoAction cacheReplaceSegmentsFormsAction = new CacheReplaceOneUndoAction(Cache, hvoParaSeg, kflidSegmentForms, iSegForm, iSegForm, realSegForms.ToArray()); cacheReplaceSegmentsFormsAction.DoIt(); if (Cache.ActionHandlerAccessor != null) { Cache.ActionHandlerAccessor.AddAction(cacheReplaceSegmentsFormsAction); } // Get the phrase wordform form the phraseAnnotation. int hvoOldWordform = WfiWordform.GetWfiWordformFromInstanceOf(Cache, hvoCbaPhrase); // delete old annotation. (In the future, this may be orphaned so that it may be reused.) WfiWordform wffOld = WfiWordform.CreateFromDBObject(Cache, hvoOldWordform, false) as WfiWordform; phraseAnnotation.DeleteUnderlyingObject(); // see if we can delete the phrase wordform from our wordinventory. Set<int> delObjIds; StTxtPara.TryDeleteWordforms(Cache, new int[] { wffOld.Hvo }, hvoParasInView, out delObjIds); return realSegForms; }
/// <summary> /// Make one, and do the action (with notification). /// </summary> public static void SetItUp(FdoCache cache, int hvo, int flid, int ihvoMin, int ihvoLim, int[] newValues) { CacheReplaceOneUndoAction action = new CacheReplaceOneUndoAction(cache, hvo, flid, ihvoMin, ihvoLim, newValues); action.DoIt(); }