예제 #1
0
		/// <summary>
		/// This is invoked (using reflection) by an XmlRDEBrowseView when the user presses
		/// "Enter" in an RDE view that is displaying lexeme form and definition.
		/// (Maybe also on loss of focus, switch domain, etc?)
		/// It creates a new entry, lexeme form, and sense that are linked to the specified domain.
		/// Typically, later, a call to RDEMergeSense will be made to see whether this
		/// new entry should be merged into some existing sense.
		/// Note that this method is NOT responsible to insert the new sense into
		/// the fake property tagList of hvoDomain. (The caller will do that.)
		/// </summary>
		/// <param name="hvoDomain">database id of the semantic domain</param>
		/// <param name="tagList">id of the inverse relation for the senses that belong to the
		/// domain</param>
		/// <param name="columns"></param>
		/// <param name="rgtss"></param>
		/// <param name="cache"></param>
		/// <param name="stringTbl"></param>
		public static int RDENewSense(int hvoDomain, int tagList,
			List<XmlNode> columns, ITsString[] rgtss, FdoCache cache, StringTable stringTbl)
		{
			Debug.Assert(hvoDomain != 0);
			Debug.Assert(rgtss.Length == columns.Count);

			// Make a new sense in a new entry.
			ILexEntry le = cache.LangProject.LexDbOA.EntriesOC.Add(
				new LexEntry());
			IMoForm morph = null;

			// create a LexSense that has the given definition and semantic domain
			// Needs to be LexSense, since later calls use non-interface methods.
			LexSense ls = (LexSense)le.SensesOS.Append(new LexSense());

			ILgWritingSystemFactory wsf = cache.LanguageWritingSystemFactoryAccessor;
			// go through each column and store the appropriate information.
			for (int i = 0; i < columns.Count; ++i)
			{
				// Review: Currently we key off the column labels to determine which columns
				// correspond to CitationForm and which correspond to Definition.
				// Ideally we'd like to get at the flids used to build the column display strings.
				// Instead of passing in only ITsStrings, we could pass in a structure containing
				// an index of strings with any corresponding flids.  Here we'd expect strings
				// based upon either LexemeForm.Form or LexSense.Definition. We could probably
				// do this as part of the solution to handling duplicate columns in LT-3763.
				XmlNode column = columns[i] as XmlNode;
				string columnLabel = XmlUtils.GetManditoryAttributeValue(column, "label");
				string[] columnLabelComponents = columnLabel.Split(new char[] {' ', ':'});
				// get column label without writing system or extraneous information.
				string columnBasicLabel = columnLabelComponents[0];
				if (!String.IsNullOrEmpty(columnBasicLabel) && stringTbl != null)
					columnBasicLabel = stringTbl.LocalizeAttributeValue(columnBasicLabel);
				ITsTextProps ttp = rgtss[i].get_PropertiesAt(0);
				int var;
				int ws = ttp.GetIntPropValues((int)FwTextPropType.ktptWs, out var);
				Debug.Assert(ws != 0);

				ITsString tssStr = rgtss[i];
				string sStr = tssStr.Text;
				if (sStr == null)
					sStr = ""; // otherwise Trim below blows up.
				sStr = sStr.Trim();

				if (columnBasicLabel == Strings.ksWord)
				{
					// This is a lexeme form.

					if (morph == null)
						morph = MoForm.MakeMorph(cache, le, tssStr);
					Debug.Assert(le.LexemeFormOAHvo != 0);
					if (morph is IMoStemAllomorph)
					{
						// Make sure we have a proper allomorph and MSA for this new entry and sense.
						// (See LT-1318 for details and justification.)
						MoMorphTypeCollection typesCol = new MoMorphTypeCollection(cache);
						if (sStr.IndexOf(' ') > 0)
							morph.MorphTypeRA = typesCol.Item(MoMorphType.kmtPhrase);
						else
							morph.MorphTypeRA = typesCol.Item(MoMorphType.kmtStem);
						morph.Form.SetAlternative(sStr, ws);
					}
				}
				else if (columnBasicLabel == Strings.ksDefinition)
				{
					// This is a Definition.
					if (sStr != "")
						ls.Definition.SetAlternative(sStr, ws);
				}
				else
				{
					Debug.Fail("column (" + columnLabel + ") not supported.");
				}
			}
			if (morph == null)
				morph = le.LexemeFormOA = new MoStemAllomorph();

			ls.RDEAddDomain(hvoDomain, tagList, cache);

			if (le.MorphoSyntaxAnalysesOC.Count == 0)
			{
				// Commonly, it's a new entry with no MSAs; make sure it has at least one.
				// This way of doing it allows a good bit of code to be shared with the normal
				// creation path, as if the user made a stem but didn't fill in any grammatical
				// information.
				DummyGenericMSA dummyMsa = new DummyGenericMSA();
				if (morph != null && morph is IMoAffixForm)
					dummyMsa.MsaType = MsaType.kUnclassified;
				else
					dummyMsa.MsaType = MsaType.kStem;
				ls.DummyMSA = dummyMsa;
			}

			// We don't want a partial MSA created, so don't bother doing anything
			// about setting ls.MorphoSyntaxAnalysisRA

			// LT-1731: adding to make sure new entries are added to the lexicon
			//	record list (full edit,...)
			cache.PropChanged(null, PropChangeType.kpctNotifyAll,
				cache.LangProject.LexDbOA.Hvo,
				(int)LexDb.LexDbTags.kflidEntries, 0, 1, 0);

			return ls.Hvo;
		}
예제 #2
0
		/// <summary>
		/// Get the morph type and class ID for the given input string.
		/// </summary>
		/// <param name="cache">The cache to look in.</param>
		/// <param name="types">Collection of all of the MoMorphType objects.</param>
		/// <param name="fullForm">The MoForm form, plus optional key characters before and/or after the form.</param>
		/// <param name="clsidForm">Return the clsid for the form.</param>
		/// <returns>The MoMorphType indicated by the possible markers.</returns>
		/// <exception cref="ArgumentException">
		/// Thrown in the following cases:
		/// 1. The input form is an empty string,
		/// 2. The imput form is improperly marked according to the current settings of the
		///		MoMorphType objects.
		/// </exception>
		public static IMoMorphType FindMorphType(FdoCache cache, MoMorphTypeCollection types,
			ref string fullForm, out int clsidForm)
		{
			Debug.Assert(cache != null);
			Debug.Assert(fullForm != null);

			clsidForm = MoStemAllomorph.kclsidMoStemAllomorph;	// default
			IMoMorphType mt = null;
			fullForm = fullForm.Trim();
			if (fullForm.Length == 0)
				throw new ArgumentException("The form is empty.", "fullForm");

			string sLeading;
			string sTrailing;
			GetAffixMarkers(cache, fullForm, out sLeading, out sTrailing);

			/*
			 Not dealt with.
			 particle	(ambiguous: particle, circumfix, root, stem)
			 circumfix	(ambiguous: particle, circumfix, root, stem)
			 root		(ambiguous: particle, circumfix, root, stem)
			 bound root	(ambiguous: bound root, bound stem)
			 infixing interfix	(ambiguous: infixing interfix, infix)
			 prefixing interfix	(ambiguous: prefixing interfix, prefix)
			 suffixing interfix	(ambiguous: suffixing interfix, suffix)
			 End of not dealt with.

			What we do deal with.
			 prefix-	(ambiguous: prefixing interfix, prefix)
			=simulfix=
			-suffix		(ambiguous: suffixing interfix, suffix)
			-infix-		(ambiguous: infixing interfix, infix)
			~suprafix~
			=enclitic
			 proclitic=
			*bound stem	(ambiguous: bound root, bound stem)
			 stem		(ambiguous: particle, circumfix, root, stem)
			End of what we do deal with.

			For ambiguous cases, pick 'root' and 'bound root', as per LarryH's suggestion on 11/18/2003.
			(Changed: May, 2004). For ambiguous cases, pick 'stem' and 'bound stem',
			as per WordWorks May, 2004 meeting (Andy Black & John Hatton).
			For ambiguous cases, pick 'infix', 'prefix', and 'suffix'.
			 */
			if (sLeading == types.Item(kmtStem).Prefix && sTrailing == types.Item(kmtStem).Postfix)
			{
				mt = types.Item(kmtStem);	// may be ambiguous with particle, root, and circumfix
			}
			else if (sLeading == types.Item(kmtPrefix).Prefix && sTrailing == types.Item(kmtPrefix).Postfix)
			{
				mt = types.Item(kmtPrefix); // may be ambiguous with prefixing interfix
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtInfix).Prefix && sTrailing == types.Item(kmtInfix).Postfix)
			{
				mt = types.Item(kmtInfix);	// may be ambiguous with infixing interfix
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtSuffix).Prefix && sTrailing == types.Item(kmtSuffix).Postfix)
			{
				mt = types.Item(kmtSuffix);	// may be ambiguous with suffixing interfix
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtBoundStem).Prefix && sTrailing == types.Item(kmtBoundStem).Postfix)
			{
				mt = types.Item(kmtBoundStem);	// may be ambiguous with bound root
			}
			else if (sLeading == types.Item(kmtProclitic).Prefix && sTrailing == types.Item(kmtProclitic).Postfix)
			{
				mt = types.Item(kmtProclitic);
			}
			else if (sLeading == types.Item(kmtEnclitic).Prefix && sTrailing == types.Item(kmtEnclitic).Postfix)
			{
				mt = types.Item(kmtEnclitic);
			}
			else if (sLeading == types.Item(kmtSimulfix).Prefix && sTrailing == types.Item(kmtSimulfix).Postfix)
			{
				mt = types.Item(kmtSimulfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtSuprafix).Prefix && sTrailing == types.Item(kmtSuprafix).Postfix)
			{
				mt = types.Item(kmtSuprafix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtBoundRoot).Prefix && sTrailing == types.Item(kmtBoundRoot).Postfix)
			{
				mt = types.Item(kmtBoundRoot);
			}
			else if (sLeading == types.Item(kmtRoot).Prefix && sTrailing == types.Item(kmtRoot).Postfix)
			{
				mt = types.Item(kmtRoot);
			}
			else if (sLeading == types.Item(kmtParticle).Prefix && sTrailing == types.Item(kmtParticle).Postfix)
			{
				mt = types.Item(kmtParticle);
			}
			else if (sLeading == types.Item(kmtCircumfix).Prefix && sTrailing == types.Item(kmtCircumfix).Postfix)
			{
				mt = types.Item(kmtCircumfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtPrefixingInterfix).Prefix && sTrailing == types.Item(kmtPrefixingInterfix).Postfix)
			{
				mt = types.Item(kmtPrefixingInterfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtInfixingInterfix).Prefix && sTrailing == types.Item(kmtInfixingInterfix).Postfix)
			{
				mt = types.Item(kmtInfixingInterfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else if (sLeading == types.Item(kmtSuffixingInterfix).Prefix && sTrailing == types.Item(kmtSuffixingInterfix).Postfix)
			{
				mt = types.Item(kmtSuffixingInterfix);
				clsidForm = MoAffixAllomorph.kclsidMoAffixAllomorph;
			}
			else
			{
				if (sLeading == null && sTrailing == null)
					throw new Exception(String.Format(Strings.ksInvalidUnmarkedForm0, fullForm));
				else if (sLeading == null)
					throw new Exception(String.Format(Strings.ksInvalidForm0Trailing1, fullForm, sTrailing));
				else if (sTrailing == null)
					throw new Exception(String.Format(Strings.ksInvalidForm0Leading1, fullForm, sLeading));
				else
					throw new Exception(String.Format(Strings.ksInvalidForm0Leading1Trailing2, fullForm, sLeading, sTrailing));
			}

			if (sLeading != null)
				fullForm = fullForm.Substring(sLeading.Length);
			if (sTrailing != null)
				fullForm = fullForm.Substring(0, fullForm.Length - sTrailing.Length);

			// Handle prhase
			if (mt.Guid.ToString().ToLower() == MoMorphType.kguidMorphStem)
			{
				if (fullForm.IndexOf(" ") != -1)
					mt = types.Item(kmtPhrase);
			}

			// Check to see if it has any of the reserved characters remaining,
			// as we have now stripped them off the ends,
			// and it is illegal to have them internal to the form.
			// (SteveMc) But is it? What about hyphenated words? Or contractions?
			// if ((MiscUtils.IndexOfAnyString(fullForm, prefixMarkers, 0, out iMatchedPrefix) > -1) ||
			// 	(MiscUtils.IndexOfAnyString(fullForm, postfixMarkers, 0, out iMatchedPrefix) > -1))
			// {
			// 	throw new Exception("\"" + fullForm + "\" is not a valid morpheme. It should not have a reserved morpheme marker within the form. Did you forget spaces?");
			// }

			return mt;
		}
예제 #3
0
		/// <summary>
		/// Get a set of hvos that are suitable for targets to a reference property.
		/// Subclasses should override this method to return a sensible list of IDs.
		/// </summary>
		/// <param name="flid">The reference property that can store the IDs.</param>
		/// <returns>A set of hvos.</returns>
		public override Set<int> ReferenceTargetCandidates(int flid)
		{
			Set<int> set = null;
			switch (flid)
			{
				case (int)MoForm.MoFormTags.kflidMorphType:
					set = new Set<int>(m_cache.LangProject.LexDbOA.MorphTypesOA.PossibilitiesOS.HvoArray);
					// Remove affix types.
					MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
					set.Remove(types.Item(MoMorphType.kmtCircumfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtInfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtPrefix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSimulfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSuffix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSuprafix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtInfixingInterfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtPrefixingInterfix).Hvo);
					set.Remove(types.Item(MoMorphType.kmtSuffixingInterfix).Hvo);
					break;
				case (int)MoStemAllomorph.MoStemAllomorphTags.kflidPhoneEnv:
					set = PhEnvironment.ValidEnvironments(m_cache);
					break;
				case (int)MoStemAllomorph.MoStemAllomorphTags.kflidStemName:
					set = new Set<int>();
					//List<CmPossibility> poses = m_cache.LangProject.PartsOfSpeechOA.ReallyReallyAllPossibilities;
					int ownerID = OwnerHVO;
					int ownerClass = m_cache.GetIntProperty(ownerID, (int)CmObjectFields.kflidCmObject_Class);
					if (ownerClass == LexEntry.kclsidLexEntry)
					{
						ILexEntry entry = LexEntry.CreateFromDBObject(m_cache, ownerID);
						foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC)
						{
							if (msa is IMoStemMsa)
							{
								IMoStemMsa infstemmsa = (IMoStemMsa)msa;
								IPartOfSpeech pos = infstemmsa.PartOfSpeechRA;
								if (pos != null)
								{
									foreach (IMoStemName sn in pos.AllStemNames)
										set.Add(sn.Hvo);
								}
							}
						}
					}
					break;
				default:
					set = base.ReferenceTargetCandidates(flid);
					break;
			}
			return set;
		}
예제 #4
0
		/// <summary>
		/// Get a set of hvos that are suitable for targets to a reference property.
		/// Subclasses should override this method to return a sensible list of IDs.
		/// </summary>
		/// <param name="flid">The reference property that can store the IDs.</param>
		/// <returns>A set of hvos.</returns>
		public override Set<int> ReferenceTargetCandidates(int flid)
		{
			Set<int> set = null;
			switch (flid)
			{
				case (int)MoForm.MoFormTags.kflidMorphType:
					set = new Set<int>(m_cache.LangProject.LexDbOA.MorphTypesOA.PossibilitiesOS.HvoArray);
					// Remove root and stem types.
					MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
					set.Remove(types.Item(MoMorphType.kmtBoundRoot).Hvo);
					set.Remove(types.Item(MoMorphType.kmtBoundStem).Hvo);
					set.Remove(types.Item(MoMorphType.kmtClitic).Hvo);
					set.Remove(types.Item(MoMorphType.kmtEnclitic).Hvo);
					set.Remove(types.Item(MoMorphType.kmtParticle).Hvo);
					set.Remove(types.Item(MoMorphType.kmtProclitic).Hvo);
					set.Remove(types.Item(MoMorphType.kmtRoot).Hvo);
					set.Remove(types.Item(MoMorphType.kmtStem).Hvo);
					set.Remove(types.Item(MoMorphType.kmtPhrase).Hvo);
					set.Remove(types.Item(MoMorphType.kmtDiscontiguousPhrase).Hvo);
					if (OwningFlid == (int)LexEntry.LexEntryTags.kflidAlternateForms)
						set.Remove(types.Item(MoMorphType.kmtCircumfix).Hvo); // only for lexemeform
					break;
				case (int)MoAffixForm.MoAffixFormTags.kflidInflectionClasses:
					set = new Set<int>();
					//List<CmPossibility> poses = m_cache.LangProject.PartsOfSpeechOA.ReallyReallyAllPossibilities;
					int ownerID = OwnerHVO;
					int ownerClass = m_cache.GetIntProperty(ownerID, (int)CmObjectFields.kflidCmObject_Class);
					if (ownerClass == LexEntry.kclsidLexEntry)
					{
						ILexEntry entry = LexEntry.CreateFromDBObject(m_cache, ownerID);
						foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC)
						{
							if (msa is IMoInflAffMsa)
							{
								IMoInflAffMsa infafxmsa = (IMoInflAffMsa)msa;
								IPartOfSpeech pos = infafxmsa.PartOfSpeechRA;
								if (pos != null)
								{
									foreach (IMoInflClass ic in pos.AllInflectionClasses)
										set.Add(ic.Hvo);
								}
							}
							// Review: is this correct?  I think the TO POS is the relevant
							// one for derivational affixes, but maybe nothing is.
							// HAB says: From is the correct one to use for the allomorphs.  The From indicates
							// the category to which the affix attaches.  This category is the one that
							// may have the inflection classes, one or more of which this allomorph may go with.
							else if (msa is IMoDerivAffMsa)
							{
								IMoDerivAffMsa drvafxmsa = (IMoDerivAffMsa)msa;
								IPartOfSpeech pos = drvafxmsa.FromPartOfSpeechRA;
								if (pos != null)
								{
									foreach (IMoInflClass ic in pos.AllInflectionClasses)
										set.Add(ic.Hvo);
								}
							}
						}
					}
					break;
				default:
					set = base.ReferenceTargetCandidates(flid);
					break;
			}
			return set;
		}
예제 #5
0
		/// <summary>
		/// Gets a set of all hvos of all valid morph type references for this MoForm
		/// </summary>
		/// <returns>A set of hvos.</returns>
		public Set<int> GetAllMorphTypeReferenceTargetCandidates()
		{
			Set<int> set = new Set<int>(m_cache.LangProject.LexDbOA.MorphTypesOA.PossibilitiesOS.HvoArray);
			MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
			if (OwningFlid == (int)LexEntry.LexEntryTags.kflidAlternateForms)
				set.Remove(types.Item(MoMorphType.kmtCircumfix).Hvo); // only for lexemeform
			return set;
		}
예제 #6
0
		private bool IsStemType(int hvo)
		{
			MoMorphTypeCollection types = new MoMorphTypeCollection(m_cache);
			if ((hvo == types.Item(MoMorphType.kmtBoundRoot).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtBoundStem).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtEnclitic).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtParticle).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtProclitic).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtRoot).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtStem).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtClitic).Hvo) ||
				// Andy: no! circumfixes are affixes, not stems: (hvo == types.Item(MoMorphType.kmtCircumfix).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtPhrase).Hvo) ||
				(hvo == types.Item(MoMorphType.kmtDiscontiguousPhrase).Hvo) )
				return true;
			return false;
		}