コード例 #1
0
        private IWfiMorphBundle MakeBundle(IWfiAnalysis wa, ILexSense sense)
        {
            var mb = Cache.ServiceLocator.GetInstance <IWfiMorphBundleFactory>().Create();

            wa.MorphBundlesOS.Add(mb);
            mb.SenseRA = sense;
            return(mb);
        }
コード例 #2
0
        private IWfiGloss MakeGloss(IWfiAnalysis wa, string form)
        {
            var wg = Cache.ServiceLocator.GetInstance <IWfiGlossFactory>().Create();

            wa.MeaningsOC.Add(wg);
            wg.Form.SetAnalysisDefaultWritingSystem(form);
            return(wg);
        }
コード例 #3
0
        private IWfiMorphBundle MakeBundle(IWfiAnalysis wa, string form)
        {
            var mb = Cache.ServiceLocator.GetInstance <IWfiMorphBundleFactory>().Create();

            wa.MorphBundlesOS.Add(mb);
            mb.Form.SetVernacularDefaultWritingSystem(form);
            return(mb);
        }
コード例 #4
0
 // Check that the specified WfiAnalysis includes at least one morpheme bundle, and that all morpheme
 // bundles have the specified property set. Return true if all is well.
 private static bool CheckPropSetForAllMorphs(IWfiAnalysis wa, int flid)
 {
     if (wa.MorphBundlesOS.Count == 0)
     {
         return(false);
     }
     return(wa.MorphBundlesOS.All(bundle => wa.Cache.DomainDataByFlid.get_ObjectProp(bundle.Hvo, flid) != 0));
 }
コード例 #5
0
		/// <summary>
		/// Update the analysis to what the sandbox is currently.
		/// </summary>
		/// <returns>'true', if anything changed, otherwise 'false'.</returns>
		public bool UpdateAnalysis(IWfiAnalysis anal)
		{
			CheckDisposed();

			var uram = new UpdateRealAnalysisMethod(this, m_caches, m_choices, anal);
			var result = uram.UpdateRealAnalysis();
			m_caches.DataAccess.ClearDirty();
			return result;
		}
コード例 #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="argument">The xCore Command object.</param>
        /// <returns>true</returns>
        public bool OnAnalysisDisapprove(object argument)
        {
            IWfiAnalysis anal = Analysis;

            Debug.Assert(anal != null, "Could not find analysis object.");
            SetNewStatus(anal, 2);

            return(true);
        }
コード例 #7
0
ファイル: Ling_WfiTests.cs プロジェクト: vkarthim/FieldWorks
        private IWfiMorphBundle MakeCompleteBundle(IWfiAnalysis wa)
        {
            var bundle = MakeBundle(wa);

            bundle.SenseRA = MakeCompleteSense();
            bundle.MsaRA   = bundle.SenseRA.MorphoSyntaxAnalysisRA;
            bundle.MorphRA = ((ILexEntry)bundle.SenseRA.Owner).LexemeFormOA;
            return(bundle);
        }
コード例 #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="wa"></param>
        /// <returns></returns>
        public bool IsHumanApproved(IWfiAnalysis wa)
        {
            ICmAgentEvaluation cae;

            if (AnalysisApprovalTable.TryGetValue(wa, out cae))
            {
                return(cae.Approves);
            }
            return(false);            // no opinion
        }
コード例 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="argument">The xCore Command object.</param>
        /// <returns>true</returns>
        public bool OnShowHumanApprovedAnalysisConc(object argument)
        {
            IWfiAnalysis anal = Analysis;

            Debug.Assert(anal != null, "Could not find analysis object.");

            ShowConcDlg(anal);

            return(true);
        }
コード例 #10
0
        /// <summary>
        /// Update the analysis to what the sandbox is currently.
        /// </summary>
        /// <returns>'true', if anything changed, otherwise 'false'.</returns>
        public bool UpdateAnalysis(IWfiAnalysis anal)
        {
            CheckDisposed();

            var uram   = new UpdateRealAnalysisMethod(this, m_caches, m_choices, anal);
            var result = uram.UpdateRealAnalysis();

            m_caches.DataAccess.ClearDirty();
            return(result);
        }
コード例 #11
0
        /// <summary>
        /// Given a wa provide the best guess based on glosses for that analysis (made in or outside of texts).
        /// </summary>
        /// <param name="wa"></param>
        /// <returns></returns>
        public IAnalysis GetBestGuess(IWfiAnalysis wa)
        {
            IAnalysis wag;

            if (GuessTable.TryGetValue(wa, out wag))
            {
                return(wag);
            }
            return(new NullWAG());
        }
コード例 #12
0
        bool IsNotDisapproved(IWfiAnalysis wa)
        {
            ICmAgentEvaluation cae;

            if (AnalysisApprovalTable.TryGetValue(wa, out cae))
            {
                return(cae.Approves);
            }
            return(true);            // no opinion
        }
コード例 #13
0
        public LexiconSense AddSense()
        {
            LexiconSense sense       = null;
            bool         lexemeAdded = false;

            using (m_lexicon.ActivationContext.Activate())
            {
                NonUndoableUnitOfWorkHelper.Do(m_lexicon.Cache.ActionHandlerAccessor, () =>
                {
                    IWfiWordform wordform;
                    if (!m_lexicon.TryGetWordform(m_key.LexicalForm, out wordform))
                    {
                        wordform    = m_lexicon.CreateWordform(m_key.LexicalForm);
                        lexemeAdded = true;
                    }
                    // For wordforms, our "senses" could be new meanings of an analysis for the word
                    // or it could be a brand new analysis. Because we have no idea what the user actually
                    // wanted, we just assume the worst (they want to create a new analysis for the word
                    // with a new meaning).
                    IWfiAnalysis analysis = m_lexicon.Cache.ServiceLocator.GetInstance <IWfiAnalysisFactory>().Create();
                    wordform.AnalysesOC.Add(analysis);
                    analysis.ApprovalStatusIcon = (int)Opinions.approves;                              // Assume the analysis from the external application is user approved
                    IMoStemAllomorph morph      = m_lexicon.Cache.ServiceLocator.GetInstance <IMoStemAllomorphRepository>().AllInstances().FirstOrDefault(allo =>
                    {
                        ITsString tss = allo.Form.StringOrNull(m_lexicon.DefaultVernWs);
                        if (tss != null)
                        {
                            return(tss.Text == LexicalForm.Normalize(NormalizationForm.FormD));
                        }
                        return(false);
                    });
                    if (morph != null)
                    {
                        IWfiMorphBundle mb = m_lexicon.Cache.ServiceLocator.GetInstance <IWfiMorphBundleFactory>().Create();
                        analysis.MorphBundlesOS.Add(mb);
                        mb.MorphRA = morph;
                        var entry  = morph.OwnerOfClass <ILexEntry>();
                        mb.SenseRA = entry.SensesOS[0];
                        mb.MsaRA   = entry.SensesOS[0].MorphoSyntaxAnalysisRA;
                    }
                    IWfiGloss gloss = m_lexicon.Cache.ServiceLocator.GetInstance <IWfiGlossFactory>().Create();
                    analysis.MeaningsOC.Add(gloss);
                    sense = new WfiGlossLexiconSense(m_lexicon, m_key, gloss);
                });
            }
            if (lexemeAdded)
            {
                m_lexicon.OnLexemeAdded(this);
            }
            m_lexicon.OnLexiconSenseAdded(this, sense);
            return(sense);
        }
コード例 #14
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Adds a new sense to the lexeme with the specified information
        /// </summary>
        /// ------------------------------------------------------------------------------------
        public LexSense AddSenseToEntry(LexemeType type, string lexicalForm, int homograph)
        {
            LexicalProviderManager.ResetLexicalProviderTimer();
            Logger.WriteEvent("Adding new sense to lexeme '" + lexicalForm + "' from an external application");

            return(NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () =>
            {
                string guid = string.Empty;
                switch (type)
                {
                case LexemeType.Word:
                    {
                        IWfiWordform dbWordform = GetDbWordform(lexicalForm);
                        if (dbWordform == null)
                        {
                            throw new ArgumentException("Entry in the lexicon not found for the specified information");
                        }

                        // For wordforms, our "senses" could be new meanings of an analysis for the word
                        // or it could be a brand new analysis. Because we have no idea what the user actually
                        // wanted, we just assume the worst (they want to create a new analysis for the word
                        // with a new meaning).
                        IWfiAnalysis dbAnalysis = m_cache.ServiceLocator.GetInstance <IWfiAnalysisFactory>().Create();
                        dbWordform.AnalysesOC.Add(dbAnalysis);
                        guid = kAnalysisPrefix + dbAnalysis.Guid;
                        break;
                    }

                default:
                    {
                        ILexEntry dbEntry = GetDbLexeme(type, lexicalForm, homograph);
                        if (dbEntry == null)
                        {
                            throw new ArgumentException("Entry in the lexicon not found for the specified information");
                        }

                        if (dbEntry.SensesOS.Count == 1 && dbEntry.SensesOS[0].Gloss.StringCount == 0)
                        {
                            // An empty sense exists (probably was created during a call to AddLexeme)
                            guid = dbEntry.SensesOS[0].Guid.ToString();
                            break;
                        }

                        ILexSense newSense = m_cache.ServiceLocator.GetInstance <ILexSenseFactory>().Create(
                            dbEntry, new SandboxGenericMSA(), null);
                        guid = newSense.Guid.ToString();
                        break;
                    }
                }
                return new LexSense(guid);
            }));
        }
コード例 #15
0
        private IWfiAnalysis SetupAnalysisForEntry(int hvoCba0_0, string gloss, ILexSense lexEntry1_Sense1, out WfiWordform wf)
        {
            int hvoWf = WfiWordform.GetWfiWordformFromInstanceOf(Cache, hvoCba0_0);

            wf = new WfiWordform(Cache, hvoWf);
            IWfiAnalysis analysis = wf.AnalysesOC.Add(new WfiAnalysis());

            analysis.CategoryRA = (lexEntry1_Sense1.MorphoSyntaxAnalysisRA as MoStemMsa).PartOfSpeechRA;
            IWfiGloss wfigloss = analysis.MeaningsOC.Add(new WfiGloss());

            wfigloss.Form.SetAlternative(gloss, Cache.DefaultAnalWs);
            return(analysis);
        }
コード例 #16
0
        /// <summary>
        /// Add the items for this WfiAnalysis (itself and ones it owns).
        /// </summary>
        void AddAnalysisItems(IWfiAnalysis wa)
        {
            AddItem(wa,
                    MakeAnalysisStringRep(wa, m_cache, StyleSheet != null, (m_owner as SandboxBase).RawWordformWs), true);
            foreach (var gloss in wa.MeaningsOC)
            {
                AddItem(gloss, MakeGlossStringRep(gloss, m_cache, StyleSheet != null), true);
            }

            //add the "new word gloss" option

            AddItem(wa, MakeSimpleString(ITextStrings.ksNewWordGloss), false, WfiGlossTags.kClassId);
        }
コード例 #17
0
		/// <summary>
		/// Make one. Everything interesting happens when it is given a root object, however.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="analysis"></param>
		/// <param name="configurationNode"></param>
		/// <param name="stringTable"></param>
		public AnalysisInterlinearRs(FdoCache cache, IWfiAnalysis analysis,
			XmlNode configurationNode, StringTable stringTable) : base(cache)
		{
			if (analysis == null)
				throw new ArgumentNullException("analysis");
			if (configurationNode == null)
				throw new ArgumentNullException("configurationNode");

			m_configurationNode = configurationNode;
			m_wfiAnalysis = analysis;
			m_wordform = m_wfiAnalysis.Wordform;
			//			RightMouseClickedEvent += new FwRightMouseClickEventHandler(InterlinDocChild_RightMouseClickedEvent);
		}
コード例 #18
0
        public void NewGlossNewLexEntryNewLexSense()
        {
            // load sandbox for first 'xxxa'
            var cba0_0 = GetNewAnalysisOccurence(m_text1, 0, 0, 0);

            m_sandbox.SwitchWord(cba0_0);

            // verify that the word gloss is empty
            ITsString tssEmpty     = TsStringUtils.MakeString("", Cache.DefaultAnalWs);
            ITsString tssWordGloss = m_sandbox.GetTssInSandbox(InterlinLineChoices.kflidWordGloss,
                                                               Cache.DefaultAnalWs);

            CompareTss(tssEmpty, tssWordGloss);
            // add a new word gloss and confirm the analysis.
            ITsString tssWordGlossInSandbox = m_sandbox.SetTssInSandbox(InterlinLineChoices.kflidWordGloss,
                                                                        Cache.DefaultAnalWs, "0.0.xxxa");
            // mark the count of LexEntries
            int cEntriesOrig = Cache.LangProject.LexDbOA.Entries.Count();
            // verify no analyses exist for this wordform;
            IWfiWordform wf = cba0_0.Analysis.Wordform;

            Assert.AreEqual(0, wf.AnalysesOC.Count);

            // set word pos, to first possibility (e.g. 'adjunct')
            int hvoSbWordPos = m_sandbox.SelectIndexInCombo(InterlinLineChoices.kflidWordPos, 0, 0);

            Assert.IsFalse(hvoSbWordPos == 0);             // select nonzero pos

            // confirm the analysis (making a real analysis and a LexSense)
            var wag          = m_sandbox.ConfirmAnalysis();
            var glossFactory = Cache.ServiceLocator.GetInstance <IWfiGlossFactory>();

            IWfiGloss wfiGloss = wag.Gloss;

            CompareTss(tssWordGlossInSandbox, wfiGloss.Form.get_String(Cache.DefaultAnalWs));
            // confirm we have only one analysis and that it is monomorphemic
            IWfiAnalysis wfiAnalysis = wag.WfiAnalysis;

            Assert.AreEqual(wf, wag.Wordform, "Expected confirmed analysis to be owned by the original wordform.");
            Assert.AreEqual(1, wf.AnalysesOC.Count);
            Assert.AreEqual(1, wfiAnalysis.MorphBundlesOS.Count);
            Assert.AreEqual(1, wfiAnalysis.MeaningsOC.Count);

            // make sure the strings of the wfi gloss matches the strings of the lex gloss.
            ValidateSenseWithAnalysis(m_sandbox.GetLexSenseForWord(), wfiGloss, hvoSbWordPos);

            // make sure a new entry is in the Lexicon.
            int cEntriesAfter = Cache.LangProject.LexDbOA.Entries.Count();

            Assert.AreEqual(cEntriesOrig + 1, cEntriesAfter);
        }
コード例 #19
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="wa"></param>
 /// <returns>by default, returns Human agent (e.g. could be approved in text)</returns>
 public OpinionAgent GetOpinionAgent(IWfiAnalysis wa)
 {
     if (IsHumanApproved(wa))
     {
         return(OpinionAgent.Human);
     }
     if (IsParserApproved(wa))
     {
         return(OpinionAgent.Parser);
     }
     if (IsComputerApproved(wa))
     {
         return(OpinionAgent.Computer);
     }
     return(OpinionAgent.Human);
 }
コード例 #20
0
        /// <summary>
        /// Make one. Everything interesting happens when it is given a root object, however.
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="analysis"></param>
        /// <param name="configurationNode"></param>
        /// <param name="stringTable"></param>
        public AnalysisInterlinearRs(FdoCache cache, IWfiAnalysis analysis,
                                     XmlNode configurationNode, StringTable stringTable) : base(cache)
        {
            if (analysis == null)
            {
                throw new ArgumentNullException("analysis");
            }
            if (configurationNode == null)
            {
                throw new ArgumentNullException("configurationNode");
            }

            m_configurationNode = configurationNode;
            m_wfiAnalysis       = analysis;
            m_wordform          = m_wfiAnalysis.Wordform;
            //			RightMouseClickedEvent += new FwRightMouseClickEventHandler(InterlinDocChild_RightMouseClickedEvent);
        }
コード例 #21
0
        public void PickLexGlossCreatingNewAnalysis()
        {
            var cba0_0 = GetNewAnalysisOccurence(m_text1, 0, 0, 0);

            m_sandbox.SwitchWord(cba0_0);
            ILexEntry lexEntry1_Entry;
            ILexSense lexEntry1_Sense1;

            SetupLexEntryAndSense("xxxa", "0.0.xxxa", out lexEntry1_Entry, out lexEntry1_Sense1);

            // mark the count of LexEntries
            int cEntriesOrig = Cache.LangProject.LexDbOA.Entries.Count();

            // add a new word gloss
            m_sandbox.SetTssInSandbox(InterlinLineChoices.kflidWordGloss,
                                      Cache.DefaultAnalWs, "0.0.xxxa");
            IWfiWordform wf = cba0_0.Analysis.Wordform;
            // set word pos, to first possibility (e.g. 'adjunct')
            int hvoSbWordPos = m_sandbox.SelectIndexInCombo(InterlinLineChoices.kflidWordPos, 0, 0);

            // confirm the analysis (making a real analysis and a LexSense)
            var       wag      = m_sandbox.ConfirmAnalysis();
            IWfiGloss wfiGloss = wag.Gloss;

            // make sure we didn't add entries or senses to the Lexicon.
            int cEntriesAfter = Cache.LangProject.LexDbOA.Entries.Count();

            Assert.AreEqual(cEntriesOrig, cEntriesAfter);
            Assert.AreEqual(1, lexEntry1_Entry.SensesOS.Count);

            // make sure the sense matches the existing one.
            ILexSense sense = m_sandbox.GetLexSenseForWord();

            Assert.AreEqual(lexEntry1_Sense1.Hvo, sense.Hvo);
            // make sure the morph is linked to our lexicon sense, msa, and part of speech.
            ValidateSenseWithAnalysis(sense, wfiGloss, hvoSbWordPos);

            // confirm we have created a new analysis and that it is monomorphemic
            IWfiAnalysis wfiAnalysis = wag.WfiAnalysis;

            Assert.AreEqual(wf, wag.Wordform, "Expected confirmed analysis to be owned by the original wordform.");
            Assert.AreEqual(1, wf.AnalysesOC.Count);
            Assert.AreEqual(1, wfiAnalysis.MorphBundlesOS.Count);
            Assert.AreEqual(1, wfiAnalysis.MeaningsOC.Count);
        }
コード例 #22
0
        private static void MergeDuplicateGlosses(IWfiAnalysis wa)
        {
            var glosses = wa.MeaningsOC.ToList();

            for (int i = 0; i < glosses.Count; i++)
            {
                var wgKeep = glosses[i];
                for (int j = glosses.Count - 1; j > i; j--)
                {
                    var wgDup = glosses[j];
                    if (DuplicateGlosses(wgKeep, wgDup))
                    {
                        CmObject.ReplaceReferences(wgDup, wgKeep);
                        wgDup.Delete();
                        glosses.RemoveAt(j);
                    }
                }
            }
        }
コード例 #23
0
 public void RemoveSense(LexiconSense sense)
 {
     NonUndoableUnitOfWorkHelper.Do(m_lexicon.Cache.ActionHandlerAccessor, () =>
     {
         var glossSense = (WfiGlossLexiconSense)sense;
         if (!glossSense.Gloss.Analysis.OccurrencesInTexts.Any(seg => seg.AnalysesRS.Contains(glossSense.Gloss)))
         {
             IWfiAnalysis analysis = glossSense.Gloss.Analysis;
             if (analysis.MeaningsOC.Count == 1 && !analysis.OccurrencesInTexts.Any())
             {
                 analysis.Delete();
             }
             else
             {
                 glossSense.Gloss.Delete();
             }
         }
     });
 }
コード例 #24
0
        private void FinishSettingAnalysis(AnalysisTree newAnalysisTree, AnalysisTree oldAnalysisTree)
        {
            if (newAnalysisTree.Analysis == oldAnalysisTree.Analysis)
            {
                return;
            }
            List <int> msaHvoList = new List <int>();
            // Collecting for the new analysis is probably overkill, since the MissingEntries combo will only have MSAs
            // that are already referenced outside of the focus box (namely by the Senses). It's unlikely, therefore,
            // that we could configure the Focus Box in such a state as to remove the last link to an MSA in the
            // new analysis.  But just in case it IS possible...
            IWfiAnalysis newWa = newAnalysisTree.WfiAnalysis;

            if (newWa != null)
            {
                // Make sure this analysis is marked as user-approved (green check mark)
                Cache.LangProject.DefaultUserAgent.SetEvaluation(newWa, Opinions.approves);
            }
        }
コード例 #25
0
        public void SetAgentOpinion()
        {
            ICmAgent     agent = Cache.LangProject.DefaultComputerAgent;
            IWfiWordform wf    = WfiWordformServices.FindOrCreateWordform(Cache,
                                                                          TsStringUtils.MakeTss("xxxyyyzzz12234", Cache.DefaultVernWs));
            IWfiAnalysis wa = Cache.ServiceLocator.GetInstance <IWfiAnalysisFactory>().Create();

            wf.AnalysesOC.Add(wa);
            Assert.AreEqual(Opinions.noopinion, wa.GetAgentOpinion(agent));

            wa.SetAgentOpinion(agent, Opinions.approves);
            Assert.AreEqual(Opinions.approves, wa.GetAgentOpinion(agent));

            wa.SetAgentOpinion(agent, Opinions.disapproves);
            Assert.AreEqual(Opinions.disapproves, wa.GetAgentOpinion(agent));

            wa.SetAgentOpinion(agent, Opinions.noopinion);
            Assert.AreEqual(Opinions.noopinion, wa.GetAgentOpinion(agent));
        }
コード例 #26
0
        public void HumanApprovedParserPreviouslyApprovedButNowRejectedAnalysisSurvives()
        {
            IWfiWordform theThreeLittlePigs = CheckAnalysisSize("theThreeLittlePigsTEST", 0, true);

            ParseResult  result = null;
            IWfiAnalysis anal   = null;

            UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () =>
            {
                // Pig entry
                ILexEntry pigN            = m_entryFactory.Create();
                IMoStemAllomorph pigNForm = m_stemAlloFactory.Create();
                pigN.AlternateFormsOS.Add(pigNForm);
                pigNForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("pigNTEST", m_vernacularWS.Handle);
                IMoStemMsa pigNMsa = m_stemMsaFactory.Create();
                pigN.MorphoSyntaxAnalysesOC.Add(pigNMsa);
                ILexSense pigNSense = Cache.ServiceLocator.GetInstance <ILexSenseFactory>().Create();
                pigN.SensesOS.Add(pigNSense);

                // Human approved anal. Start with parser approved, but then it failed.
                var analFactory = Cache.ServiceLocator.GetInstance <IWfiAnalysisFactory>();
                var mbFactory   = Cache.ServiceLocator.GetInstance <IWfiMorphBundleFactory>();
                // Only analysis: human approved, previously parser approved but no longer produced.
                anal = analFactory.Create();
                theThreeLittlePigs.AnalysesOC.Add(anal);
                IWfiMorphBundle mb = mbFactory.Create();
                anal.MorphBundlesOS.Add(mb);
                mb.MorphRA = pigNForm;
                mb.MsaRA   = pigNMsa;
                HumanAgent.SetEvaluation(anal, Opinions.approves);
                ParserAgent.SetEvaluation(anal, Opinions.approves);
                CheckEvaluationSize(anal, 2, true, "anal");
                CheckAnalysisSize("theThreeLittlePigsTEST", 1, true);

                result = new ParseResult(Enumerable.Empty <ParseAnalysis>());
            });

            m_filer.ProcessParse(theThreeLittlePigs, ParserPriority.Low, result);
            ExecuteIdleQueue();
            CheckEvaluationSize(anal, 2, false, "analHvo");
            Assert.IsTrue(anal.IsValidObject, "analysis should end up with one evaluation and not be deleted");
        }
コード例 #27
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Removes the sense with the specified ID and guid from the DB.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        private void RemoveSense(string senseId, Guid guid)
        {
            if (senseId.StartsWith(kAnalysisPrefix))
            {
                IWfiAnalysis dbAnalysis = m_cache.ServiceLocator.GetInstance <IWfiAnalysisRepository>().GetObject(guid);
                IWfiWordform dbWordform = (IWfiWordform)dbAnalysis.Owner;
                dbWordform.AnalysesOC.Remove(dbAnalysis);
            }
            else
            {
                ILexSense dbSense = m_cache.ServiceLocator.GetInstance <ILexSenseRepository>().GetObject(guid);
                ILexEntry dbEntry = (ILexEntry)dbSense.Owner;

                // Make sure we keep at least one sense around. This seems to be required.
                if (dbEntry.SensesOS.Count > 1)
                {
                    dbEntry.SensesOS.Remove(dbSense);
                }
            }
        }
コード例 #28
0
			/// <summary>
			/// This contructor is only to be used by the
			/// </summary>
			/// <param name="owner"></param>
			/// <param name="caches"></param>
			/// <param name="choices"></param>
			/// <param name="anal"></param>
			public UpdateRealAnalysisMethod(SandboxBase owner, CachePair caches, InterlinLineChoices choices,
				IWfiAnalysis anal)
			{
				m_sandbox = owner;
				m_caches = caches;
				m_hvoSbWord = kSbWord; // kSbWord really is a constant, not a real hvo.
				//m_hvoWordform = hvoWordform;
				//m_hvoWfiAnalysis = hvoWfiAnalysis;
				m_anal = anal;
				//m_hvoWordGloss = hvoWordGloss;
				m_sda = m_caches.DataAccess;
				m_sdaMain = m_caches.MainCache.MainCacheAccessor;
				m_cmorphs = m_sda.get_VecSize(m_hvoSbWord, ktagSbWordMorphs);
				m_choices = choices;
				//m_tssForm = tssForm;
				var servLoc = m_caches.MainCache.ServiceLocator;
				m_moFormRepos = servLoc.GetInstance<IMoFormRepository>();
				m_senseRepos = servLoc.GetInstance<ILexSenseRepository>();
				m_msaRepos = servLoc.GetInstance<IMoMorphSynAnalysisRepository>();
			}
コード例 #29
0
			public GetRealAnalysisMethod(IHelpTopicProvider helpTopicProvider, SandboxBase owner,
				CachePair caches, int hvoSbWord, AnalysisTree oldAnalysis, IWfiAnalysis wa,
				IWfiGloss gloss, InterlinLineChoices choices, ITsString tssForm,
				bool fWantOnlyWfiAnalysis) : this()
			{
				m_helpTopicProvider = helpTopicProvider;
				m_sandbox = owner;
				m_caches = caches;
				m_hvoSbWord = hvoSbWord;
				m_oldAnalysis = oldAnalysis;
				m_wf = oldAnalysis.Wordform;
				m_wa = wa;
				m_wg = gloss;
				m_sda = m_caches.DataAccess;
				m_sdaMain = m_caches.MainCache.MainCacheAccessor;
				m_cmorphs = m_sda.get_VecSize(m_hvoSbWord, ktagSbWordMorphs);
				m_choices = choices;
				m_tssForm = tssForm;
				m_fWantOnlyWfiAnalysis = fWantOnlyWfiAnalysis;
			}
コード例 #30
0
        public void HumanHasNoopinionParserHadApprovedButNoLongerApprovesRemovesAnalysis()
        {
            IWfiWordform threeLittlePigs = CheckAnalysisSize("threeLittlePigsTEST", 0, true);

            ParseResult  result = null;
            IWfiAnalysis anal   = null;

            UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () =>
            {
                // Pig entry
                ILexEntry pigN            = m_entryFactory.Create();
                IMoStemAllomorph pigNForm = m_stemAlloFactory.Create();
                pigN.AlternateFormsOS.Add(pigNForm);
                pigNForm.Form.VernacularDefaultWritingSystem = TsStringUtils.MakeString("pigNTEST", m_vernacularWS.Handle);
                IMoStemMsa pigNMsa = m_stemMsaFactory.Create();
                pigN.MorphoSyntaxAnalysesOC.Add(pigNMsa);
                ILexSense pigNSense = Cache.ServiceLocator.GetInstance <ILexSenseFactory>().Create();
                pigN.SensesOS.Add(pigNSense);

                // Human no-opinion anal. Parser had approved, but then it failed to produce it.
                var analFactory = Cache.ServiceLocator.GetInstance <IWfiAnalysisFactory>();
                var mbFactory   = Cache.ServiceLocator.GetInstance <IWfiMorphBundleFactory>();
                // Human no-opinion anal. Parser had approved, but then it failed to produce it.
                anal = analFactory.Create();
                threeLittlePigs.AnalysesOC.Add(anal);
                IWfiMorphBundle mb = mbFactory.Create();
                anal.MorphBundlesOS.Add(mb);
                mb.MorphRA = pigNForm;
                mb.MsaRA   = pigNMsa;
                HumanAgent.SetEvaluation(anal, Opinions.noopinion);
                ParserAgent.SetEvaluation(anal, Opinions.approves);
                CheckEvaluationSize(anal, 1, true, "anal");
                CheckAnalysisSize("threeLittlePigsTEST", 1, true);

                result = new ParseResult(Enumerable.Empty <ParseAnalysis>());
            });

            m_filer.ProcessParse(threeLittlePigs, ParserPriority.Low, result);
            ExecuteIdleQueue();
            Assert.IsFalse(anal.IsValidObject, "analysis should end up with no evaluations and be deleted.");
        }
コード例 #31
0
        private IWfiMorphBundle MakeBundleDefault(IWfiAnalysis wa, string form, string gloss, string pos)
        {
            var options = new MakeBundleOptions();

            options.LexEntryForm = form;
            options.MakeMorph    = (mff) =>
            {
                Guid slotType = GetSlotType(mff);
                IMoMorphSynAnalysis msa;
                var entry = MakeEntry(mff.Replace("-", ""), pos, slotType, out msa);
                return(entry.LexemeFormOA);
            };
            options.MakeSense = (entry) =>
            {
                var msa   = entry.MorphoSyntaxAnalysesOC.ToList()[0];
                var sense = MakeSense(entry, gloss, msa);
                return(sense);
            };
            options.MakeMsa = (sense) => { return(sense.MorphoSyntaxAnalysisRA); };
            return(MakeBundle(wa, options));
        }
コード例 #32
0
            /// <summary>
            /// This contructor is only to be used by the
            /// </summary>
            /// <param name="owner"></param>
            /// <param name="caches"></param>
            /// <param name="choices"></param>
            /// <param name="anal"></param>
            public UpdateRealAnalysisMethod(SandboxBase owner, CachePair caches, InterlinLineChoices choices,
                                            IWfiAnalysis anal)
            {
                m_sandbox   = owner;
                m_caches    = caches;
                m_hvoSbWord = kSbWord;                 // kSbWord really is a constant, not a real hvo.
                //m_hvoWordform = hvoWordform;
                //m_hvoWfiAnalysis = hvoWfiAnalysis;
                m_anal = anal;
                //m_hvoWordGloss = hvoWordGloss;
                m_sda     = m_caches.DataAccess;
                m_sdaMain = m_caches.MainCache.MainCacheAccessor;
                m_cmorphs = m_sda.get_VecSize(m_hvoSbWord, ktagSbWordMorphs);
                m_choices = choices;
                //m_tssForm = tssForm;
                var servLoc = m_caches.MainCache.ServiceLocator;

                m_moFormRepos = servLoc.GetInstance <IMoFormRepository>();
                m_senseRepos  = servLoc.GetInstance <ILexSenseRepository>();
                m_msaRepos    = servLoc.GetInstance <IMoMorphSynAnalysisRepository>();
            }
コード例 #33
0
        public void NewGlossExistingLexEntryNewLexSense()
        {
            var cba0_0 = GetCba(0, 0, 0);

            m_sandbox.SwitchWord(cba0_0);
            ILexEntry lexEntry1_Entry;
            ILexSense lexEntry1_Sense1;

            SetupLexEntryAndSense("xxxa", "xxxa.existingsense1", out lexEntry1_Entry, out lexEntry1_Sense1);

            // mark the count of LexEntries
            int cEntriesOrig = Cache.LangProject.LexDbOA.Entries.Count();

            // add a new word gloss
            m_sandbox.SetTssInSandbox(InterlinLineChoices.kflidWordGloss,
                                      Cache.DefaultAnalWs, "0.0.xxxa");
            IWfiWordform wf = cba0_0.Analysis.Wordform;
            // set word pos, to first possibility (e.g. 'adjunct')
            int hvoSbWordPos = m_sandbox.SelectIndexInCombo(InterlinLineChoices.kflidWordPos, 0, 0);

            // confirm the analysis (making a real analysis and a LexSense)
            var       wag      = m_sandbox.ConfirmAnalysis();
            IWfiGloss wfiGloss = wag.Gloss;

            // make sure we didn't add entries to the Lexicon.
            int cEntriesAfter = Cache.LangProject.LexDbOA.Entries.Count();

            Assert.AreEqual(cEntriesOrig, cEntriesAfter);

            // confirm we have only one analysis and that it is monomorphemic
            IWfiAnalysis wfiAnalysis = wag.WfiAnalysis;

            Assert.AreEqual(wf, wag.Wordform, "Expected confirmed analysis to be owned by the original wordform.");
            Assert.AreEqual(1, wf.AnalysesOC.Count);
            Assert.AreEqual(1, wfiAnalysis.MorphBundlesOS.Count);
            Assert.AreEqual(1, wfiAnalysis.MeaningsOC.Count);

            // make sure the strings of the wfi gloss matches the strings of the lex gloss.
            ValidateSenseWithAnalysis(m_sandbox.GetLexSenseForWord(), wfiGloss, hvoSbWordPos);
        }
コード例 #34
0
        private IWfiMorphBundle MakeBundle(IWfiAnalysis wa, MakeBundleOptions mbOptions)
        {
            var bundle = Cache.ServiceLocator.GetInstance <IWfiMorphBundleFactory>().Create();

            wa.MorphBundlesOS.Add(bundle);
            var morph = mbOptions.MakeMorph(mbOptions.LexEntryForm);

            bundle.MorphRA = morph;
            var sense = mbOptions.MakeSense(morph.Owner as ILexEntry);

            bundle.SenseRA = sense;
            var msa = mbOptions.MakeMsa(sense);

            bundle.MsaRA = msa;
            if (mbOptions.MakeInflType != null)
            {
                var inflType = mbOptions.MakeInflType(morph);
                bundle.InflTypeRA = inflType;
            }

            return(bundle);
        }
コード例 #35
0
ファイル: Ling_WfiTests.cs プロジェクト: bbriggs/FieldWorks
		private IWfiGloss MakeCompleteGloss(IWfiAnalysis wa)
		{
			var wg = MakeGloss(wa);
			wg.Form.AnalysisDefaultWritingSystem = Cache.TsStrFactory.MakeString("a gloss", Cache.DefaultAnalWs);
			return wg;
		}
コード例 #36
0
ファイル: Ling_WfiTests.cs プロジェクト: bbriggs/FieldWorks
		private IWfiMorphBundle MakeBundle(IWfiAnalysis wa)
		{
			var bundle = Cache.ServiceLocator.GetInstance<IWfiMorphBundleFactory>().Create();
			wa.MorphBundlesOS.Add(bundle);
			return bundle;
		}
コード例 #37
0
ファイル: Ling_WfiTests.cs プロジェクト: bbriggs/FieldWorks
		private IWfiMorphBundle MakeCompleteBundle(IWfiAnalysis wa)
		{
			var bundle = MakeBundle(wa);
			bundle.SenseRA = MakeCompleteSense();
			bundle.MsaRA = bundle.SenseRA.MorphoSyntaxAnalysisRA;
			bundle.MorphRA = ((ILexEntry) bundle.SenseRA.Owner).LexemeFormOA;
			return bundle;
		}
コード例 #38
0
			/// <summary>
			/// Get the most appropriate WfiGloss from among those belonging to the given WfiAnalysis.
			/// The goal is to match as closely as possible the strings found in sda.get_MultiStringAlt(hvoWord, ktagSbWordGloss, ws)
			/// for each ws in wsIds. Ideally we find an alternative where all writing systems match exactly.
			/// Failing that, one where as many as possible match, and the others are blank.
			/// </summary>
			/// <param name="wfiAnalysis"></param>
			/// <param name="wsIds"></param>
			/// <param name="sda"></param>
			/// <param name="hvoWord"></param>
			/// <returns></returns>
			internal static IWfiGloss GetBestGloss(IWfiAnalysis wfiAnalysis, List<int> wsIds, ISilDataAccess sda, int hvoWord)
			{
				IWfiGloss best = null;
				int cBestMatch = 0;
				int cBestBlanks = 0; // number of non-matching alternatives that are blank, in the best match so far
				foreach (IWfiGloss possibleGloss in wfiAnalysis.MeaningsOC)
				{
					int cMatch = 0;
					int cBlanks = 0; // number of non-matching alternatives that are blank, in the current item.
					foreach (int wsId in wsIds)
					{
						ITsString tssGloss = sda.get_MultiStringAlt(hvoWord, ktagSbWordGloss, wsId);
						ITsString tssMainGloss = possibleGloss.Form.get_String(wsId);
						string sdaGloss = tssGloss.Text;
						string smainGloss = tssMainGloss.Text;

						if (tssGloss.Equals(tssMainGloss))
							cMatch++;
						else if (tssMainGloss.Length == 0)
							cBlanks++;
						else
						{
							cMatch = int.MinValue; // non-matching alternative on the WfiGloss, this one is no good for sure
							cBlanks = int.MinValue;
						}
					}
					// This one is better if:
					// - it has more matches
					// - it has as many matches and more relevant empty alternatives
					// - it is as good otherwise and has fewer non-relevant alternatives.
					if (cMatch > cBestMatch
						|| (cMatch == cBestMatch && cBlanks > cBestBlanks)
						|| (cMatch == cBestMatch && cBlanks == cBestBlanks && best != null && AdditionalAlternatives(possibleGloss, wsIds) < AdditionalAlternatives(best, wsIds)))
					{
						cBestMatch = cMatch;
						cBestBlanks = cBlanks;
						best = possibleGloss;
					}
				}
				// we won't return something where nothing matched, just because it had a blank alternative
				return cBestMatch > 0 ? best : null;
			}
コード例 #39
0
ファイル: Ling_WfiTests.cs プロジェクト: bbriggs/FieldWorks
		private IWfiGloss MakeGloss(IWfiAnalysis wa)
		{
			var wg = Cache.ServiceLocator.GetInstance<IWfiGlossFactory>().Create();
			wa.MeaningsOC.Add(wg);
			return wg;
		}
コード例 #40
0
			/// <summary>
			/// A trivial analysis, the sort created when just doing word glossing, doesn't really specify anything,
			/// though it may have one morph bundle that just matches the whole wordform.
			/// It may possibly specify a part of speech, in which case it must match the one the user entered
			/// to be reusable.
			/// </summary>
			/// <param name="possibleAnalysis"></param>
			/// <returns></returns>
			private bool IsTrivialAnalysis(IWfiAnalysis possibleAnalysis)
			{
				if (possibleAnalysis.CategoryRA != null
					&& possibleAnalysis.CategoryRA != m_caches.RealObject(m_sda.get_ObjectProp(m_hvoSbWord, ktagSbWordPos)) as IPartOfSpeech)
					return false;
				if (possibleAnalysis.MorphBundlesOS.Count == 0)
					return true;
				if (possibleAnalysis.MorphBundlesOS.Count > 1)
					return false;
				var mb = possibleAnalysis.MorphBundlesOS[0];
				return (mb.MorphRA == null && mb.MsaRA == null && mb.SenseRA == null);
			}
コード例 #41
0
		protected void CheckEvaluationSize(IWfiAnalysis analysis, int expectedSize, bool isStarting, string additionalMessage)
		{
			int actualSize = analysis.EvaluationsRC.Count;
			string msg = String.Format("Wrong number of {0} evaluations for analysis: {1} ({2})", isStarting ? "starting" : "ending", analysis.Hvo, additionalMessage);
			Assert.AreEqual(expectedSize, actualSize, msg);
		}
コード例 #42
0
ファイル: LexEntryUi.cs プロジェクト: bbriggs/FieldWorks
		// Currently only called from WCF (11/21/2013 - AP)
		public static void DisplayEntry(FdoCache cache, Mediator mediatorIn,
			IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWfIn, IWfiAnalysis wfa)
		{
			DisplayEntries(cache, null, mediatorIn, helpProvider, helpFileKey, tssWfIn, wfa);
		}
コード例 #43
0
		private void SetNewStatus(IWfiAnalysis anal, int newStatus)
		{
			int currentStatus = anal.ApprovalStatusIcon;
			if (currentStatus == newStatus)
				return;

			UndoableUnitOfWorkHelper.Do(MEStrings.ksUndoChangingApprovalStatus,
				MEStrings.ksRedoChangingApprovalStatus, Cache.ActionHandlerAccessor,
				() =>
					{
						if (currentStatus == 1)
							anal.MoveConcAnnotationsToWordform();
						anal.ApprovalStatusIcon = newStatus;
						if (newStatus == 1)
						{
							// make sure default senses are set to be real values,
							// since the user has seen the defaults, and approved the analysis based on them.
							foreach (var mb in anal.MorphBundlesOS)
							{
								var currentSense = mb.SenseRA;
								if (currentSense == null)
									mb.SenseRA = mb.DefaultSense;
							}
						}
					});

			// Wipe all of the old slices out, so we get new numbers and newly placed objects.
			// This fixes LT-5935. Also removes the need to somehow make the virtual properties like HumanApprovedAnalyses update.
			m_dataEntryForm.RefreshList(true);
		}
コード例 #44
0
		private IWfiMorphBundle MakeBundle(IWfiAnalysis wa, string form)
		{
			var mb = Cache.ServiceLocator.GetInstance<IWfiMorphBundleFactory>().Create();
			wa.MorphBundlesOS.Add(mb);
			mb.Form.SetVernacularDefaultWritingSystem(form);
			return mb;
		}
コード例 #45
0
			private void AddComboItems(ref int hvoEmptyGloss, ITsStrBldr tsb, IWfiAnalysis wa)
			{
				IList<int> wsids = m_sandbox.m_choices.WritingSystemsForFlid(InterlinLineChoices.kflidWordGloss);
				foreach (IWfiGloss gloss in wa.MeaningsOC)
				{
					int glossCount = 0;

					foreach (int ws in wsids)
					{
						ITsString nextWsGloss = gloss.Form.get_String(ws);
						if (nextWsGloss.Length > 0)
						{
							// Append a comma if there are more glosses.
							if (glossCount > 0)
								tsb.Replace(tsb.Length, tsb.Length, ", ", null);

							// Append a Ws label if there are more than one Ws.
							if (wsids.Count > 1)
							{
								tsb.ReplaceTsString(tsb.Length, tsb.Length, WsListManager.WsLabel(m_caches.MainCache, ws));
								tsb.Replace(tsb.Length, tsb.Length, " ", null);
							}
							int oldLen = tsb.Length;
							tsb.ReplaceTsString(oldLen, oldLen, nextWsGloss);
							int color = (int)CmObjectUi.RGB(Color.Blue);
							tsb.SetIntPropValues(oldLen, tsb.Length, (int)FwTextPropType.ktptForeColor,
								(int)FwTextPropVar.ktpvDefault, color);
							glossCount++;
						}
					}
					// (LT-1428) If we find an empty gloss, use this hvo for "New word gloss" instead of 0.
					if (glossCount == 0 && wsids.Count > 0)
					{
						hvoEmptyGloss = gloss.Hvo;
						ITsPropsBldr tpbUserWs = TsPropsBldrClass.Create();
						tpbUserWs.SetIntPropValues((int)FwTextPropType.ktptWs, 0, m_wsUser);
						tsb.Replace(tsb.Length, tsb.Length, ITextStrings.ksEmpty, tpbUserWs.GetTextProps());
					}

					ComboList.Items.Add(new HvoTssComboItem(gloss.Hvo, tsb.GetString()));
					tsb.Clear();
				}
			}
コード例 #46
0
		private IWfiMorphBundle MakeBundle(IWfiAnalysis wa, ILexSense sense)
		{
			var mb = Cache.ServiceLocator.GetInstance<IWfiMorphBundleFactory>().Create();
			wa.MorphBundlesOS.Add(mb);
			mb.SenseRA = sense;
			return mb;
		}
コード例 #47
0
		private IWfiGloss MakeGloss(IWfiAnalysis wa, string form)
		{
			var wg = Cache.ServiceLocator.GetInstance<IWfiGlossFactory>().Create();
			wa.MeaningsOC.Add(wg);
			wg.Form.SetAnalysisDefaultWritingSystem(form);
			return wg;
		}
コード例 #48
0
ファイル: LexEntryUi.cs プロジェクト: bbriggs/FieldWorks
		internal static void DisplayEntries(FdoCache cache, IWin32Window owner, Mediator mediatorIn,
			IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWfIn, IWfiAnalysis wfa)
		{
			ITsString tssWf = tssWfIn;
			var entries = FindEntriesForWordformUI(cache, tssWf, wfa);

			StringTable stOrig;
			Mediator mediator;
			IVwStylesheet styleSheet;
			bool fRestore = EnsureFlexTypeSetup(cache, mediatorIn, out stOrig, out mediator, out styleSheet);
			try
			{

				if (entries == null || entries.Count == 0)
				{
					ILexEntry entry = ShowFindEntryDialog(cache, mediator, tssWf, owner);
					if (entry == null)
						return;
					entries = new List<ILexEntry>(1);
					entries.Add(entry);
				}
				DisplayEntriesRecursive(cache, owner, mediator, styleSheet, helpProvider, helpFileKey, entries, tssWf);
			}
			finally
			{
				// Restore the original string table in the mediator if needed.
				if (fRestore)
					mediator.StringTbl = stOrig;
			}
		}
コード例 #49
0
		/// <summary>
		/// Add the items for this WfiAnalysis (itself and ones it owns).
		/// </summary>
		void AddAnalysisItems(IWfiAnalysis wa)
		{
			AddItem(wa,
				MakeAnalysisStringRep(wa, m_cache, StyleSheet != null, (m_owner as SandboxBase).RawWordformWs), true);
			foreach (var gloss in wa.MeaningsOC)
			{
				AddItem(gloss, MakeGlossStringRep(gloss, m_cache, StyleSheet != null), true);
			}

			//add the "new word gloss" option

			AddItem(wa, MakeSimpleString(ITextStrings.ksNewWordGloss), false, WfiGlossTags.kClassId);
		}
コード例 #50
0
ファイル: Ling_WfiTests.cs プロジェクト: bbriggs/FieldWorks
		private void RemoveReferenceAnalysisFromFirstSeg(IText text, IWfiAnalysis analysis)
		{
			var seg = ((IStTxtPara)text.ContentsOA.ParagraphsOS[0]).SegmentsOS[0];
			seg.AnalysesRS.Remove(analysis);
		}
コード例 #51
0
		// Make a string representing a WfiAnalysis, suitable for use in a combo box item.
		static internal ITsString MakeAnalysisStringRep(IWfiAnalysis wa, FdoCache fdoCache, bool fUseStyleSheet, int wsVern)
		{
			//			ITsTextProps boldItalicAnalysis = BoldItalicAnalysis(fdoCache);
			//			ITsTextProps italicAnalysis = ItalicAnalysis(fdoCache, Sandbox.SandboxVc.krgbRed);
			ITsTextProps posTextProperties = PartOfSpeechTextProperties(fdoCache, true, fUseStyleSheet);
			ITsTextProps formTextProperties = FormTextProperties(fdoCache, fUseStyleSheet, wsVern);
			ITsTextProps glossTextProperties = GlossTextProperties(fdoCache, true, fUseStyleSheet);
			ITsStrBldr tsb = TsStrBldrClass.Create();
			ISilDataAccess sda = fdoCache.MainCacheAccessor;
			int cmorph = wa.MorphBundlesOS.Count;
			if (cmorph == 0)
				return TsStringUtils.MakeTss(ITextStrings.ksNoMorphemes, fdoCache.DefaultUserWs);
			bool fRtl = fdoCache.ServiceLocator.WritingSystemManager.Get(wsVern).RightToLeftScript;
			int start = 0;
			int lim = cmorph;
			int increment = 1;
			if (fRtl)
			{
				start = cmorph - 1;
				lim = -1;
				increment = -1;
			}
			for (int i = start; i != lim; i += increment)
			{
				var mb = wa.MorphBundlesOS[i];
				var mf = mb.MorphRA;
				ITsString tssForm = null;
				// Review: Appears to be similar to code in LexEntryVc.
				if (mf != null)
				{
					var entry = mf.Owner as ILexEntry;
					var lexemeForm = entry.LexemeFormOA;
					if (lexemeForm != null)
					{
						tssForm = lexemeForm.Form.get_String(wsVern);
					}
					if (tssForm == null || tssForm.Length == 0)
					{
						tssForm = entry.CitationForm.get_String(wsVern);
					}
					if (tssForm.Length == 0)
					{
						// If there isn't a lexeme form OR citation form use the form of the morph.
						tssForm = mf.Form.get_String(wsVern);
					}
				}
				else // no MoForm linked to this bundle, use its own form.
				{
					tssForm = mb.Form.get_String(wsVern);
				}
				int ichForm = tsb.Length;
				tsb.ReplaceTsString(ichForm, ichForm, tssForm);
				tsb.SetProperties(ichForm, tsb.Length,formTextProperties);

				// add category (part of speech)
				var msa = mb.MsaRA;
				tsb.Replace(tsb.Length, tsb.Length, " ", null);
				int ichMinMsa = tsb.Length;
				string interlinName = ksMissingString;
				if (msa != null)
					interlinName = msa.InterlinearAbbr;
				tsb.Replace(ichMinMsa, ichMinMsa, interlinName, posTextProperties);

				//add sense
				var sense = mb.SenseRA;
				tsb.Replace(tsb.Length, tsb.Length, " ", null);
				int ichMinSense = tsb.Length;
				if (sense != null)
				{
					ITsString tssGloss = sense.Gloss.get_String(fdoCache.DefaultAnalWs);
					tsb.Replace(ichMinSense, ichMinSense, tssGloss.Text, glossTextProperties);
				}
				else
					tsb.Replace(ichMinSense, ichMinSense, ksMissingString, glossTextProperties);

				// Enhance JohnT: use proper seps.
				tsb.Replace(tsb.Length, tsb.Length, ksPartSeparator, null);
			}
			// Delete the final separator. (Enhance JohnT: this needs to get smarter when we do
			// real seps.)
			int ichFrom = tsb.Length - ksPartSeparator.Length;
			if (ichFrom < 0)
				ichFrom = 0;
			tsb.Replace(ichFrom, tsb.Length, "", null);
			return tsb.GetString();
		}
コード例 #52
0
			/// <summary>
			///
			/// </summary>
			/// <param name="iSegment"></param>
			/// <param name="iSegForm"></param>
			/// <param name="wfiAnalysis">wfi analysis to add gloss to.</param>
			/// <param name="gloss"></param>
			/// <returns></returns>
			override internal IWfiGloss SetDefaultWordGloss(int iSegment, int iSegForm, IWfiAnalysis wfiAnalysis, out string gloss)
			{
				IWfiGloss wfiGloss = base.SetDefaultWordGloss(iSegment, iSegForm, wfiAnalysis, out gloss);
				m_pb.SetExpectedValuesForAnalysis(m_pb.SegmentFormNode(iSegment, iSegForm), wfiGloss.Hvo);
				return wfiGloss;
			}
コード例 #53
0
ファイル: LexEntryUi.cs プロジェクト: bbriggs/FieldWorks
		/// <summary>
		/// Find the list of LexEntry objects which conceivably match the given wordform.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="tssWf"></param>
		/// <param name="wfa"></param>
		/// <returns></returns>
		public static List<ILexEntry> FindEntriesForWordformUI(FdoCache cache, ITsString tssWf, IWfiAnalysis wfa)
		{
			bool duplicates = false;
			List<ILexEntry> retval = cache.ServiceLocator.GetInstance<ILexEntryRepository>().FindEntriesForWordform(cache, tssWf, wfa, ref duplicates);

			if (duplicates)
			{
				MessageBox.Show(Form.ActiveForm,
					string.Format(FdoUiStrings.ksDuplicateWordformsMsg, tssWf.Text),
					FdoUiStrings.ksDuplicateWordformsCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning);
			}
			return retval;
		}
コード例 #54
0
			virtual internal IWfiGloss SetDefaultWordGloss(int iSegment, int iSegForm, IWfiAnalysis actualWfiAnalysis, out string gloss)
			{
				gloss = "";
				// Get actual segment form.
				var analysisActual = GetAnalysis(iSegment, iSegForm);

				// Get the wordform for this segmentForm
				ITsString tssWordformBaseline = GetBaselineText(iSegment, iSegForm);

				// Find or create the current analysis of the actual annotation.
				if (actualWfiAnalysis == null)
				{
					actualWfiAnalysis = FindOrCreateWfiAnalysis(analysisActual);
				}
				// Make a new gloss based upon the wordform and segmentForm path.
				var newGloss = m_cache.ServiceLocator.GetInstance<IWfiGlossFactory>().Create();
				// Add the gloss to the WfiAnalysis.
				actualWfiAnalysis.MeaningsOC.Add(newGloss);
				gloss = String.Format("{0}.{1}.{2}", iSegment, iSegForm, tssWordformBaseline.Text);
				newGloss.Form.set_String(m_cache.DefaultAnalWs, gloss);

				// Set the new expected and actual analysis.
				SetAnalysis(iSegment, iSegForm, newGloss);
				return newGloss;
			}
コード例 #55
0
		AnalysisTree IAnalysisControlInternal.GetRealAnalysis(bool fSaveGuess, out IWfiAnalysis obsoleteAna)
		{
			obsoleteAna = null;
			return NewAnalysisTree;
		}
コード例 #56
0
		private void VerifyWfiAnalysis(int wsEn, IWfiAnalysis anal)
		{
			Assert.AreEqual("indefinite article", anal.CategoryRA.Name.get_String(wsEn).Text);
			Assert.AreEqual(1, anal.MorphBundlesOS.Count);
			IWfiMorphBundle mb = anal.MorphBundlesOS[0];
			ILexEntry entry = m_cache.LangProject.LexDbOA.Entries.ToArray()[0];
			Assert.AreEqual(entry.MorphoSyntaxAnalysesOC.ToArray()[0], mb.MsaRA);
			Assert.AreEqual(entry.LexemeFormOA, mb.MorphRA);
			Assert.AreEqual(entry.SensesOS[0].SensesOS[2], mb.SenseRA);
			Assert.AreEqual(1, anal.MeaningsOC.Count);
			IWfiGloss gloss = anal.MeaningsOC.ToArray()[0];
			Assert.AreEqual(0, gloss.Form.StringCount);
		}
コード例 #57
0
		private IWfiMorphBundle MakeBundle(IWfiAnalysis wa, MakeBundleOptions mbOptions)
		{
			var bundle = Cache.ServiceLocator.GetInstance<IWfiMorphBundleFactory>().Create();
			wa.MorphBundlesOS.Add(bundle);
			var morph = mbOptions.MakeMorph(mbOptions.LexEntryForm);
			bundle.MorphRA = morph;
			var sense = mbOptions.MakeSense(morph.Owner as ILexEntry);
			bundle.SenseRA = sense;
			var msa = mbOptions.MakeMsa(sense);
			bundle.MsaRA = msa;
			if (mbOptions.MakeInflType != null)
			{
				var inflType = mbOptions.MakeInflType(morph);
				bundle.InflTypeRA = inflType;
			}

			return bundle;
		}
コード例 #58
0
		/// -----------------------------------------------------------------------------------
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		/// -----------------------------------------------------------------------------------
		protected override void Dispose(bool disposing)
		{
			//Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
			// Must not be run more than once.
			if (IsDisposed)
				return;

			if (disposing)
			{
				if (m_oneAnalSandbox != null)
				{
					m_oneAnalSandbox.SizeChanged -= HandleSandboxSizeChanged;
				}
			}

			base.Dispose(disposing);

			if (disposing)
			{
				if (m_oneAnalSandbox != null)
				{
					m_oneAnalSandbox.Dispose();
				}
				if (m_vc != null)
					m_vc.Dispose();
			}
			m_oneAnalSandbox = null;
			m_vc = null;
			m_configurationNode = null;
			m_wordform = null;
			m_wfiAnalysis = null;
		}
コード例 #59
0
			// Answer true if the analysis is only used in one place (typically the current one).
			// It must have at most one WfiGloss and a net of one Segment that references it and its gloss if any.
			// That one segment must only reference it once.
			private bool OnlyUsedThisOnce(IWfiAnalysis oldAnalysis)
			{
				if (oldAnalysis.MeaningsOC.Count > 1)
					return false; // It's technically possible there might only be one use, but which one would we update?
				// No need to enumerate more than two! This will speed it up for words used a lot.
				var segsUsingAnalysis = oldAnalysis.ReferringObjects.Where(obj => obj is ISegment).Take(2);
				if (segsUsingAnalysis.Count() > 1)
					return false;
				ISegment seg = segsUsingAnalysis.FirstOrDefault() as ISegment;
				IAnalysis target = oldAnalysis;
				if (oldAnalysis.MeaningsOC.Count == 1)
				{
					var wfiGloss = oldAnalysis.MeaningsOC.ToArray()[0];
					var segsUsingGloss = wfiGloss.ReferringObjects.Where(obj => obj is ISegment).Take(2);
					if (segsUsingAnalysis.Count() + segsUsingGloss.Count() > 1)
						return false;
					if (seg == null)
					{
						seg = segsUsingGloss.FirstOrDefault() as ISegment;
						target = wfiGloss;
					}
				}
				if (seg == null)
					return true; // no uses at all...probably can't happen
				return seg.AnalysesRS.Where(a => a == target).Take(2).Count() <= 1;
			}
コード例 #60
0
			private IAnalysis FinishItOff()
			{
				FdoCache fdoCache = m_caches.MainCache;
				var wfRepository = fdoCache.ServiceLocator.GetInstance<IWfiWordformRepository>();
				if (m_wf == null)
				{
					IWfiWordform wf;
					// first see if we can find a matching form
					if (wfRepository.TryGetObject(m_tssForm, false, out wf))
						m_wf = wf;
					else
					{
						// The user selected a case form that did not previously have a WfiWordform.
						// Since he is confirming this analysis, we now need to create one.
						// Note: if in context of the wordforms DummyRecordList, the RecordList is
						// smart enough to handle inserting one object without having to Reload the whole list.
						m_wf = fdoCache.ServiceLocator.GetInstance<IWfiWordformFactory>().Create(m_tssForm);
					}
				}
				// If sandbox contains only an empty morpheme string, don't consider this to be a true analysis.
				// Assume that the user was not finished with his analysis (cf. LT-1621).
				if (m_sandbox.IsAnalysisEmpty)
				{
					return m_wf;
				}

				// Update the wordform with any additional wss.
				List<int> wordformWss = m_choices.OtherWritingSystemsForFlid(InterlinLineChoices.kflidWord, 0);
				// we need another way to detect the static ws for kflidWord.
				foreach (int wsId in wordformWss)
				{
					UpdateMlaIfDifferent(m_hvoSbWord, ktagSbWordForm, wsId, m_wf.Hvo, WfiWordformTags.kflidForm);
				}

				// (LT-7807 later refined by FWR-3536)
				// if we're in a special mode for adding monomorphemic words to lexicon and the user's proposed analysis is monomorphemic,
				// if there is an existing possible analysis that matches on form, gloss, and POS, use it.
				// else if there is an existing possible analysis that matches on form and gloss and has no POS,
				//	update the POS and use it.
				// else if the occurrence is currently analyzed as a particular sense and there are no other occurrences
				//  of that sense, update the gloss and/or POS of the sense to match what we want (and use it)
				// else if there is a matching entry with the right form, add a suitable sense to use
				// else make a new entry and sense to use.
				if (m_sandbox.ShouldAddWordGlossToLexicon)
				{
					IhMorphEntry.MorphItem matchingMorphItem = new IhMissingEntry.MorphItem(0, null);
					ITsString tssWf = m_wf.Form.get_String(m_sandbox.RawWordformWs);
					// go through the combo options for lex entries / senses to see if we can find any existing matches.
					using (IhMorphEntry handler = InterlinComboHandler.MakeCombo(m_helpTopicProvider, ktagWordGlossIcon, m_sandbox, 0) as SandboxBase.IhMorphEntry)
					{
						List<IhMorphEntry.MorphItem> morphItems = handler.MorphItems;
						// see if we can use an existing Sense, if it matches the word gloss and word MSA
						foreach (IhMorphEntry.MorphItem morphItem in morphItems)
						{
							// skip lex senses that do not match word gloss and pos in the Sandbox
							if (!SbWordGlossMatchesSenseGloss(morphItem))
								continue;
							if (!SbWordPosMatchesSenseMsaPos(morphItem))
								continue;
							// found a LexSense matching our Word Gloss and MSA POS
							matchingMorphItem = morphItem;
							break;
						}
						if (matchingMorphItem.m_hvoSense == 0)
						{
							// Next see if we can find an existing analysis where the gloss matches and POS is null.
							foreach (IhMorphEntry.MorphItem morphItem in morphItems)
							{
								// skip lex senses that do not match word gloss and pos in the Sandbox
								if (!SbWordGlossMatchesSenseGloss(morphItem))
									continue;
								// found a LexSense matching our Word Gloss and that has no POS.
								var pos = m_caches.RealObject(m_sda.get_ObjectProp(m_hvoSbWord, ktagSbWordPos)) as IPartOfSpeech;
								var sense = m_caches.MainCache.ServiceLocator.GetObject(morphItem.m_hvoSense) as ILexSense;
								if (sense == null)
									continue; // don't think this can happen but play safe.
								var msa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa;
								if (msa == null || msa.PartOfSpeechRA != null)
									continue; // for this case we can only use one that doesn't already have a POS.
								msa.PartOfSpeechRA = pos; // adjust it
								if (m_oldAnalysis.WfiAnalysis != null) // always?
								{
									if (m_oldAnalysis.WfiAnalysis.CategoryRA != pos)
										m_oldAnalysis.WfiAnalysis.CategoryRA = pos;
								}
								matchingMorphItem = morphItem; // and use it.
								break;
							}
						}
						if (matchingMorphItem.m_hvoSense == 0 && m_oldAnalysis != null && m_oldAnalysis.WfiAnalysis != null)
						{
							// still don't have one we can use; see whether it is legitimate to modify the current
							// analysis.
							var oldAnalysis = m_oldAnalysis.WfiAnalysis;
							if (oldAnalysis.MorphBundlesOS.Count == 1
								&& oldAnalysis.MorphBundlesOS[0].SenseRA != null
								&& oldAnalysis.MorphBundlesOS[0].SenseRA.MorphoSyntaxAnalysisRA is IMoStemMsa
								&& OnlyUsedThisOnce(oldAnalysis)
								&& OnlyUsedThisOnce(oldAnalysis.MorphBundlesOS[0].SenseRA))
							{
								// We're allowed to change the existing sense and analysis! A side effect of updating the sense
								// is updating the MSA of the morph bundle of the oldAnalysis.
								var pos = m_caches.RealObject(m_sda.get_ObjectProp(m_hvoSbWord, ktagSbWordPos)) as IPartOfSpeech;
								UpdateSense(oldAnalysis.MorphBundlesOS[0].SenseRA, pos);
								if (oldAnalysis.CategoryRA != pos)
									oldAnalysis.CategoryRA = pos;
								if (m_oldAnalysis.Gloss != null)
								{
									// if the old analysis is a gloss, update it also.
									CopyGlossesToWfiGloss(m_oldAnalysis.Gloss);
									return m_oldAnalysis.Gloss;
								}
								// Don't have an old gloss, create one.
								var newGloss = oldAnalysis.Services.GetInstance<IWfiGlossFactory>().Create();
								oldAnalysis.MeaningsOC.Add(newGloss);
								CopyGlossesToWfiGloss(newGloss);
								return newGloss;
							}
						}
						// If we get here we could not use an existing analysis with any safe modification.
						// if we couldn't use an existing sense but we match a LexEntry form,
						// add a new sense to an existing entry.
						ILexEntry bestEntry = null;
						if (morphItems.Count > 0 && matchingMorphItem.m_hvoSense == 0)
						{
							// Tried using FindBestLexEntryAmongstHomographs() but it matches
							// only CitationForm which MorphItems doesn't know anything about,
							// and doesn't match against Allomorphs which MorphItems do track
							// so this could lead to a crash (LT-9430).
							//
							// Solution: if the user specified a category, see if we can find an entry
							// with a sense using that same category
							// otherwise just add the new sense to the first entry in MorphItems.
							IhMorphEntry.MorphItem bestMorphItem = morphItems[0];
							foreach (IhMorphEntry.MorphItem morphItem in morphItems)
							{
								// skip items that do not match word main pos in the Sandbox
								if (!SbWordMainPosMatchesSenseMsaMainPos(morphItem))
									continue;
								bestMorphItem = morphItem;
								break;
							}

							bestEntry = bestMorphItem.GetPrimaryOrOwningEntry(m_caches.MainCache);
							// lookup this entry;
							matchingMorphItem = FindLexEntryMorphItem(morphItems, bestEntry);
						}

						if (matchingMorphItem.m_hvoMorph == 0)
						{
							// we didn't find a matching lex entry, so create a new entry
							ILexEntry newEntry;
							ILexSense newSense;
							IMoForm allomorph;
							handler.CreateNewEntry(true, out newEntry, out allomorph, out newSense);
						}
						else if (bestEntry != null)
						{
							// we found matching lex entry, so create a new sense for it
							var senseFactory = fdoCache.ServiceLocator.GetInstance<ILexSenseFactory>();
							ILexSense newSense = senseFactory.Create(bestEntry, new SandboxGenericMSA(), "");
							// copy over any word glosses we're showing.
							CopyGlossesToSense(newSense);
							// copy over the Word POS
							var pos = m_caches.RealObject(m_sda.get_ObjectProp(m_hvoSbWord, ktagSbWordPos)) as IPartOfSpeech;
							(newSense.MorphoSyntaxAnalysisRA as IMoStemMsa).PartOfSpeechRA = pos;
							var morph = fdoCache.ServiceLocator.GetInstance<IMoFormRepository>().GetObject(matchingMorphItem.m_hvoMorph);
							handler.UpdateMorphEntry(morph, bestEntry, newSense);
						}
						else
						{
							// we found a matching lex entry and sense, so select it.
							int iMorphItem = morphItems.IndexOf(matchingMorphItem);
							handler.HandleSelect(iMorphItem);
						}
					}
				}

				BuildMorphLists(); // Used later on in the code.
				m_hvoCategoryReal = m_caches.RealHvo(m_sda.get_ObjectProp(m_hvoSbWord, ktagSbWordPos));

				// We may need to create a new WfiAnalysis based on whether we have any sandbox gloss content.
				bool fNeedGloss = false;
				bool fWordGlossLineIsShowing = false; // Set to 'true' if the wrod gloss line is included in the m_choices fields.
				foreach (InterlinLineSpec ilc in m_choices)
				{
					if (ilc.Flid == InterlinLineChoices.kflidWordGloss)
					{
						fWordGlossLineIsShowing = true;
						break;
					}
				}
				if (fWordGlossLineIsShowing)
				{
					// flag that we need to create wfi gloss information if any configured word gloss lines have content.
					foreach (int wsId in m_choices.WritingSystemsForFlid(InterlinLineChoices.kflidWordGloss))
					{
						if (m_sda.get_MultiStringAlt(m_hvoSbWord, ktagSbWordGloss, wsId).Length > 0)
						{
							fNeedGloss = true;
							break;
						}
					}
				}

				// We decided to take this logic out (see LT-1653) because it is annoying when
				// deliberately removing a wrong morpheme breakdown guess.
				//				// We need to create (or find an existing) WfiAnalysis if we have any morphemes,
				//				// a word gloss, or a word category.
				//				bool fNeedAnalysis = fNeedGloss || m_cmorphs > 1 || m_hvoCategoryReal != 0;
				//
				//				// If we have exactly one morpheme, see if it has some non-trivial information
				//				// associated. If not, don't make an analysis.
				//				if (!fNeedGloss && m_cmorphs == 1 && m_hvoCategoryReal == 0 && m_analysisMsas[0] == 0
				//					&& m_analysisSenses[0] == 0 && m_analysisMorphs[0] == 0)
				//				{
				//					fNeedAnalysis = false;
				//				}
				//				// If there's no information at all, the 'analysis' is just the original wordform.
				//				if (!fNeedAnalysis)
				//					return m_hvoWordform;
				// OK, we have some information that corresponds to an analysis. Find or create
				// an analysis that matches.
				int wsVern = m_sandbox.RawWordformWs;
				m_wa = FindMatchingAnalysis(true);
				bool fFoundAnalysis = m_wa != null;
				if (!fFoundAnalysis)
				{
					// Clear the checksum on the wordform. This allows the parser filer to re-evaluate it and
					// delete the old analysis if it is just a simpler, parser-generated form of the one we're now making.
					m_wf.Checksum = 0;
					// Check whether there's a parser-generated analysis that the current settings
					// subsume.  If so, reuse that analysis by filling in the missing data (word gloss,
					// word category, and senses).
					// Another option is that there is an existing 'analysis' that is a trivial one,
					// created by word-only glossing. We can re-use that, filling in the other details
					// now supplied.
					var partialWa = FindMatchingAnalysis(false);
					bool fNewAnal = partialWa == null;
					if (fNewAnal)
					{
						foreach (var ana in m_wf.AnalysesOC)
						{
							if (m_oldAnalysis != null &&
								ana == m_oldAnalysis.WfiAnalysis &&
								OnlyUsedThisOnce(ana) &&
								IsAnalysisHumanApproved(m_caches.MainCache, ana))
							{
								ObsoleteAnalysis = ana;
								break;
							}
						}
						// Create one.
						var waFactory = fdoCache.ServiceLocator.GetInstance<IWfiAnalysisFactory>();
						var waNew = waFactory.Create();
						m_wf.AnalysesOC.Add(waNew);
						m_wa = waNew;
					}
					else
					{
						m_wa = partialWa;
						// For setting word glosses, we should treat this as a 'found' not new analysis
						// if it has any glosses, so we will search for and find any existing ones that match.
						fFoundAnalysis = m_wa.MeaningsOC.Count > 0;
					}
					IPartOfSpeech pos = null;
					if (m_hvoCategoryReal != 0)
						pos = fdoCache.ServiceLocator.GetInstance<IPartOfSpeechRepository>().GetObject(m_hvoCategoryReal);
					m_wa.CategoryRA = pos;
					var mbFactory = fdoCache.ServiceLocator.GetInstance<IWfiMorphBundleFactory>();
					var msaRepository = fdoCache.ServiceLocator.GetInstance<IMoMorphSynAnalysisRepository>();
					var mfRepository = fdoCache.ServiceLocator.GetInstance<IMoFormRepository>();
					var senseRepository = fdoCache.ServiceLocator.GetInstance<ILexSenseRepository>();
					var inflTypeRepository = fdoCache.ServiceLocator.GetInstance<ILexEntryInflTypeRepository>();
					for (int imorph = 0; imorph < m_cmorphs; imorph++)
					{
						IWfiMorphBundle mb;
						if (imorph >= m_wa.MorphBundlesOS.Count)
						{
							mb = mbFactory.Create();
							m_wa.MorphBundlesOS.Insert(imorph, mb);
						}
						else
						{
							mb = m_wa.MorphBundlesOS[imorph];
						}
						// An undo operation can leave stale information in the sandbox.  If
						// that happens, the stored database id values are invalid.  Set them
						// all to zero if the morph is invalid.  (See LT-3824 for a crash
						// scenario.)  This fix prevents a crash, but doesn't do anything for
						// restoring the original values before the operation that is undone.
						if (m_analysisMorphs[imorph] != 0 &&
							!m_sdaMain.get_IsValidObject(m_analysisMorphs[imorph]))
						{
							m_analysisMorphs[imorph] = 0;
							m_analysisMsas[imorph] = 0;
							m_analysisSenses[imorph] = 0;
						}
						// Set the Morph of the bundle if we know a real one; otherwise, just set its Form
						if (m_analysisMorphs[imorph] == 0)
						{
							int hvoSbMorph = m_sda.get_VecItem(m_hvoSbWord, ktagSbWordMorphs, imorph);
							mb.Form.set_String(wsVern, m_sandbox.GetFullMorphForm(hvoSbMorph));
							// Copy any other wss over, without any funny business about morpheme breaks
							// Per LT-14891, we don't allow editing of the other morph lines, so no need to set them.
							//foreach (int ws in m_choices.OtherWritingSystemsForFlid(InterlinLineChoices.kflidMorphemes, 0))
							//{
							//    mb.Form.set_String(ws,
							//        m_caches.DataAccess.get_MultiStringAlt(hvoSbMorph, ktagSbNamedObjName, ws));
							//}
						}
						else
						{
							mb.MorphRA = mfRepository.GetObject(m_analysisMorphs[imorph]);
						}
						// Set the MSA if we have one. Note that it is (pathologically) possible that the user has done
						// something in another window to destroy the MSA we remember, so don't try to set it if so.
						if (m_analysisMsas[imorph] != 0 && m_sdaMain.get_IsValidObject(m_analysisMsas[imorph]))
						{
							mb.MsaRA = msaRepository.GetObject(m_analysisMsas[imorph]);
						}
						// Likewise the Sense
						if (m_analysisSenses[imorph] != 0)
						{
							mb.SenseRA = senseRepository.GetObject(m_analysisSenses[imorph]);
							// set the InflType if we have one.
							var hvoSbInflType = GetRealHvoFromSbWmbInflType(imorph);
							mb.InflTypeRA = hvoSbInflType != 0 ? inflTypeRepository.GetObject(hvoSbInflType) : null;
						}

					}
				}
				else if (fWordGlossLineIsShowing) // If the line is not showing at all, don't bother.
				{
					// (LT-1428) Since we're using an existing WfiAnalysis,
					// We will find or create a new WfiGloss (even for blank lines)
					// if WfiAnalysis already has WfiGlosses
					//	or m_hvoWordGloss is nonzero
					//	or Sandbox has gloss content.
					bool fSbGlossContent = fNeedGloss;
					int cGloss = m_wa.MeaningsOC.Count;
					fNeedGloss = cGloss > 0 || m_wg != null || fSbGlossContent;
				}

				if (m_wa != null)
					EnsureCorrectMorphForms();

				if (!fNeedGloss || m_fWantOnlyWfiAnalysis)
				{
					return m_wa;
				}
				if (m_wg != null)
				{
					// We may consider editing it instead of making a new one.
					// But ONLY if it belongs to the right analysis!!
					if (m_wg.Owner != m_wa)
						m_wg = null;
				}
				/* These are the types of things we are trying to accomplish here.
				Problem 1 -- Correcting a spelling mistake.
					Gloss1: mn <-
				User corrects spelling to men
				Desired:
					Gloss1: men <-
				Bad result:
					Gloss1: mn
					Gloss2: men <-

				Problem 2 -- Switching to a different gloss via typing.
					Gloss1: he <-
					Gloss2: she
				User types in she rather than using dropdown box to select it
				Desired:
					Gloss1: he
					Gloss2: she <-
				Bad result:
					Gloss1: she <-
					Gloss2: she

				Problem 2A
							Gloss1: he <-
				User types in she without first using dropdown box to select "add new gloss"
				Desired:
							Gloss1: he (still used for N other occurrences)
							Gloss2: she <-
				Bad (at least dubious) result:
							Gloss1: she <- (used for this and all other occurrences)

				Problem 3 -- Adding a missing alternative when there are not duplications.
					Gloss1: en=green <-
				User adds the French equivalent
				Desired:
					Gloss1: en=green, fr=vert <-
				Bad result:
					Gloss1: en=green
					Gloss2: en=green, fr=vert <-

				The logic used to be to look for glosses with all alternatives matching or else it
				creates a new one. So 2 would actually work, but 1 and 3 were both bad.

				New logic: keep track of the starting WfiAnalysis and WfiGloss.
				Assuming we haven't changed to a new WfiAnalysis based on other changes, if there
				is a WfiGloss that matches any of the existing alternatives, we switch to that.
				Otherwise we set the alternatives of the starting WfiGloss to whatever the user
				entered. This logic would work for all three examples above, but has problems
				with the following.

				Problem -- add a missing gloss where there are identical glosses in another ws.
					Gloss1: en=them <-
				User adds Spanish gloss
				Desired:
					Gloss1: en=them, es=ellas <-
				This works ok with above logic. But now in another location the user needs to
				use the masculine them in Spanish, so changes ellas to ellos
				Desired:
					Gloss1: en=them, es=ellas
					Gloss2: en=them, es=ellos <-
				Bad result:
					Gloss1: en=them, es=ellos <-

				Eventually, we'll probably want to display a dialog box to ask users what they really want.
				"There are 15 places where "XXX" analyzed as 3pp is currently glossed
				en->"them".  Would you like to
				<radio button, selected> change them all to en->"them" sp->"ellas"?
				<radio button> leave the others glossed en->"them" and let just this one
				be en->"them" sp->"ellas"?
				<radio button> see a concordance and choose which ones to change to
				en->"them" sp->"ellas"?
				*/

				// (LT-1428, LT-12472)
				// -----------------------------
				// When the user edits a gloss,
				// (1) If there is an existing gloss matching what they just changed it to
				//		then switch this instance to point to that one.
				// (2) Else if the gloss is used only in this instance, or if it matches on all WSs that are not blank in the gloss,
				//		then apply the edits directly to the gloss.
				// (3) Else, create a new gloss.
				//-------------------------------
				var gloss = fFoundAnalysis ? FindMatchingGloss() : null;

				if (gloss == null && m_sandbox.WordGlossReferenceCount == 1)
				{
					gloss = m_wg; // update the existing gloss.
				}

				if (gloss == null)
				{
					// Create one.
					var wgFactory = fdoCache.ServiceLocator.GetInstance<IWfiGlossFactory>();
					gloss = wgFactory.Create();
					m_wa.MeaningsOC.Add(gloss);
				}
				foreach (int wsId in m_choices.WritingSystemsForFlid(InterlinLineChoices.kflidWordGloss))
				{
					ITsString tssGloss = m_sda.get_MultiStringAlt(m_hvoSbWord, ktagSbWordGloss, wsId);
					if (!tssGloss.Equals(gloss.Form.get_String(wsId)))
					{
						gloss.Form.set_String(wsId, tssGloss);
					}
				}
				return gloss;
			}