/// <summary> /// Load the information about the domains of hvoEntry. Returns false /// if the entry has no associated domains or none of them are linked to any other entries. /// </summary> /// <param name="cache"></param> /// <param name="hvoEntry"></param> /// <param name="domains"></param> /// <param name="cdaTemp"></param> /// <param name="fMoreRows"></param> /// <param name="owner"></param> /// <returns></returns> static private bool LoadDomainInfo(FdoCache cache, int hvoEntry, out int[] domainsOut, out IVwCacheDa cdaTemp, IWin32Window owner) { // This produces first the Semantic domains of the senses of the entry, // then restricts to those that occur on some other entry, // then looks up the vernacular (or, if none, analysis) name of the domains. The are sorted by // domain name. // We do left outer joins for the last two so we can distinguish the failure // modes "no SDs on senses of initial entry" versus "no other entries in those SDs" string sql1 = string.Format("select lssd2.dst, cn.txt, cn.ws from LexEntry le" + " join LexSense_ ls on ls.owner$ = le.id" + " join LexSense_SemanticDomains lssd on lssd.src = ls.id " + " left outer join LexSense_SemanticDomains lssd2 on lssd2.dst = lssd.dst" + " and exists (select * from CmObject lsother" + " join LexEntry leother on leother.id = lsother.owner$ and lsother.id = lssd2.src and leother.id != le.id)" + " left outer join CmPossibility_Name cn on lssd2.dst = cn.obj and cn.ws" + " in ({0}, {1}) where le.id = {2}" + " group by lssd2.dst, cn.txt, cn.ws" + " order by cn.txt", cache.DefaultVernWs, cache.DefaultAnalWs, hvoEntry); IOleDbCommand odc = DbOps.MakeRowSet(cache, sql1, null); bool fGotSrcDomain = false; // true if we found a semantic domain on some sense of the source entry try { bool fMoreRows; List <int> domains = new List <int>(); cdaTemp = VwCacheDaClass.Create(); for (odc.NextRow(out fMoreRows); fMoreRows; odc.NextRow(out fMoreRows)) { fGotSrcDomain = true; // any row indicates success here. int hvoDomain = DbOps.ReadInt(odc, 0); if (hvoDomain == 0) { continue; // null row, an SD that occurs on no other entry. } if (!((ISilDataAccess)cdaTemp).get_IsPropInCache(hvoDomain, RelatedWordsVc.ktagName, (int)CellarModuleDefns.kcptString, 0)) { ITsString tss = DbOps.ReadTss2(odc, 1); if (tss == null) { tss = FDO.Cellar.CmPossibility.BestAnalysisOrVernName(cache, hvoDomain); } cdaTemp.CacheStringProp(hvoDomain, RelatedWordsVc.ktagName, tss); domains.Add(hvoDomain); } } domainsOut = DbOps.ListToIntArray(domains); } finally { DbOps.ShutdownODC(ref odc); } return(fGotSrcDomain); }
void SetupDomainsForEntry(int[] domains) { m_cdaTemp.CacheVecProp(m_hvoEntry, RelatedWordsVc.ktagDomains, domains, domains.Length); // This produces first the Semantic domains of the senses of the entry, // then uses a backreference to find all senses linked to those domains. // Todo JohnT: this finds only entries that directly own senses linked to the relevant domains. // It will not find entries that only have senses with subsenses in the domain. // This is because we're specifically looking for MoForms with the same owner as the senses we found. // We'd have to do something tricky and recursive to get owning entry of a subsense. string sql2 = string.Format("select lscd.dst, cmls.owner$, mff.txt from LexSense ls" + " join CmObject cols on ls.id = cols.id and cols.owner$ = {0}" + " join LexSense_SemanticDomains lscd on lscd.src = ls.id" + " join LexSense_SemanticDomains lscd2 on lscd2.dst = lscd.dst and lscd2.src != ls.id" + " join CmObject cmls on lscd2.src = cmls.id and cmls.owner$ != {0}" + " join MoForm_ mf on mf.owner$ = cmls.owner$ and mf.OwnFlid$ = {1}" + " join MoForm_Form mff on mff.obj = mf.id and mff.ws = {2}" + " group by lscd.dst, cmls.owner$, mff.txt" + " order by lscd.dst, mff.txt", m_hvoEntry, (int)LexEntry.LexEntryTags.kflidLexemeForm, m_cache.DefaultVernWs); IOleDbCommand odc = DbOps.MakeRowSet(m_cache, sql2, null); try { bool fMoreRows; List <int> words = new List <int>(); int hvoOldDomain = 0; // to trigger change of domain on first iteration for (odc.NextRow(out fMoreRows); fMoreRows; odc.NextRow(out fMoreRows)) { int hvoNewDomain = DbOps.ReadInt(odc, 0); if (hvoNewDomain != hvoOldDomain) { if (hvoOldDomain != 0) { m_cdaTemp.CacheVecProp(hvoOldDomain, RelatedWordsVc.ktagWords, DbOps.ListToIntArray(words), words.Count); words.Clear(); } hvoOldDomain = hvoNewDomain; } int hvoWord = DbOps.ReadInt(odc, 1); // JohnT: if I was better at sql, I could no doubt figure out how to prevent // duplicates in the query above, which are caused by having two or more senses of the // same entry in the same domain. But it's easier to just eliminate them here (and maybe // even faster). if (!words.Contains(hvoWord)) { m_cdaTemp.CacheStringProp(hvoWord, RelatedWordsVc.ktagName, DbOps.ReadTss(odc, 2, m_cache.DefaultVernWs)); words.Add(hvoWord); } } if (hvoOldDomain != 0) { // Cache words of last domain. m_cdaTemp.CacheVecProp(hvoOldDomain, RelatedWordsVc.ktagWords, DbOps.ListToIntArray(words), words.Count); } int hvoLf = m_cache.MainCacheAccessor.get_ObjectProp(m_hvoEntry, (int)LexEntry.LexEntryTags.kflidLexemeForm); if (hvoLf != 0) { ITsString tssCf = m_cache.MainCacheAccessor.get_MultiStringAlt(hvoLf, (int)MoForm.MoFormTags.kflidForm, m_cache.DefaultVernWs); m_cdaTemp.CacheStringProp(m_hvoEntry, RelatedWordsVc.ktagCf, tssCf); } } finally { DbOps.ShutdownODC(ref odc); } }
/// <summary> /// Load the information about the lexical relations that link to hvoEntry. /// </summary> /// <param name="cache"></param> /// <param name="hvoEntry"></param> /// <param name="relsOut"></param> /// <param name="cdaTemp"></param> /// <param name="owner"></param> /// <returns>false if the entry has no associated lexical relations, or none of them are linked to any other entries.</returns> static private bool LoadLexicalRelationInfo(FdoCache cache, int hvoEntry, out int[] relsOut, IVwCacheDa cdaTemp, IWin32Window owner) { string sql1 = string.Format("SELECT DISTINCT tar2.Src, lrt.MappingType, tar.Ord, cn.Txt, cn.Ws, rev.Txt, rev.Ws" + " FROM LexReference_Targets tar" + " LEFT OUTER JOIN LexReference_Targets tar2 ON tar2.Src=tar.Src AND EXISTS (SELECT * FROM CmObject other WHERE other.Id=tar2.Dst AND other.Id != tar.Dst)" + " LEFT OUTER JOIN LexRefType_Members mem ON mem.Dst=tar2.Src" + " LEFT OUTER JOIN LexRefType lrt ON lrt.Id=mem.Src" + " LEFT OUTER JOIN CmPossibility_Name cn ON cn.Obj=mem.Src AND cn.Ws IN ({0}, {1})" + " LEFT OUTER JOIN LexRefType_ReverseName rev ON rev.Obj=mem.Src AND rev.Ws IN ({0}, {1})" + " WHERE tar.Dst = {2} OR tar.Dst IN (SELECT Id FROM fnGetOwnedIds({2}, {3}, {4}))", cache.DefaultVernWs, cache.DefaultAnalWs, hvoEntry, (int)LexEntry.LexEntryTags.kflidSenses, (int)LexSense.LexSenseTags.kflidSenses); IOleDbCommand odc = DbOps.MakeRowSet(cache, sql1, null); bool fGotLexRef = false; // true if we found a lexical relation for the entry or one of its senses try { bool fMoreRows; List <int> rels = new List <int>(); for (odc.NextRow(out fMoreRows); fMoreRows; odc.NextRow(out fMoreRows)) { fGotLexRef = true; int hvoLexRef = DbOps.ReadInt(odc, 0); if (hvoLexRef == 0) { continue; // null row. } if (!((ISilDataAccess)cdaTemp).get_IsPropInCache(hvoLexRef, RelatedWordsVc.ktagName, (int)CellarModuleDefns.kcptString, 0)) { int type = DbOps.ReadInt(odc, 1); int ord = DbOps.ReadInt(odc, 2); ITsString tssName = DbOps.ReadTss2(odc, 3); ITsString tssRevName = DbOps.ReadTss2(odc, 5); if (type == (int)LexRefType.MappingTypes.kmtEntryAsymmetricPair || type == (int)LexRefType.MappingTypes.kmtEntryOrSenseAsymmetricPair || type == (int)LexRefType.MappingTypes.kmtSenseAsymmetricPair) { if (ord != 0 && tssRevName != null && tssRevName.Length > 0) { tssName = tssRevName; } } else if (type == (int)LexRefType.MappingTypes.kmtEntryTree || type == (int)LexRefType.MappingTypes.kmtEntryOrSenseTree || type == (int)LexRefType.MappingTypes.kmtSenseTree) { if (ord != 0 && tssRevName != null && tssRevName.Length > 0) { tssName = tssRevName; } } cdaTemp.CacheStringProp(hvoLexRef, RelatedWordsVc.ktagName, tssName); rels.Add(hvoLexRef); } } relsOut = DbOps.ListToIntArray(rels); } finally { DbOps.ShutdownODC(ref odc); } return(fGotLexRef); }