Example #1
0
				private void AddToNameCollection(ref NamePart singleName, ref List<NamePart> nameCollection, NamePart newNamePart, int index, bool collapseAdjacentName)
				{
					string newName = newNamePart;
					newName = newName.Trim();
					NamePartOptions options = newNamePart.Options;
					int startNameCount = GetNameCount(ref singleName, ref nameCollection);
					int endNameCount;
					// Test for space separated and pattern based multi-part names
					if (newName.IndexOfAny(NameDelimiterArray) != -1)
					{
						string[] individualEntries = newName.Split(NameDelimiterArray, StringSplitOptions.RemoveEmptyEntries);
						// We don't know at this point if the names are single or will split further with
						// the next call. Test how many items are added by tracking the count at each stage.
						for (int i = 0; i < individualEntries.Length; ++i)
						{
							// Add each space separated name individually
							AddToNameCollection(ref singleName, ref nameCollection, new NamePart(individualEntries[i], options), index == -1 ? -1 : index + (i == 0 ? 0 : GetNameCount(ref singleName, ref nameCollection) - startNameCount), false);
						}
						endNameCount = GetNameCount(ref singleName, ref nameCollection);
					}
					else if (0 == (options & NamePartOptions.ExplicitCasing) &&
						EmbeddedCapsOrNumberRegex.IsMatch(newName))
					{
						Match match = SplitOnUpperRegex.Match(newName);
						int matchIndex = 0;
						while (match.Success)
						{
							// Using the match index as an increment is sufficient
							// because we know the names will not split further and
							// adjacent names will not collapse.
							GroupCollection groups = match.Groups;
							AddToNameCollection(ref singleName, ref nameCollection, new NamePart(match.Value, groups["TrailingUpper"].Success || groups["Numeric"].Success ? NamePartOptions.ExplicitCasing : NamePartOptions.None), index == -1 ? -1 : index + matchIndex, false);
							++matchIndex;
							match = match.NextMatch();
						}
						endNameCount = startNameCount + matchIndex;
					}
					else if (singleName.IsEmpty)
					{
						// We only have one name so far, so just use the string
						singleName = new NamePart(newName, options);
						endNameCount = 1;
					}
					else
					{
						// We need to now use the collection
						if (null == nameCollection)
						{
							nameCollection = new List<NamePart>();
							// First add the previously added element
							nameCollection.Add(singleName);
						}
						if (index == -1)
						{
							nameCollection.Add(new NamePart(newName, options));
						}
						else
						{
							nameCollection.Insert(index, new NamePart(newName, options));
						}
						endNameCount = startNameCount + 1;
					}

					int newNameCount;
					if (collapseAdjacentName &&
						0 != (newNameCount = (endNameCount - startNameCount))) // A name was added
					{
						// Remove duplicate names, treating the multiple parts as a split
						// name as a single name.
						if (index == -1)
						{
							index = startNameCount;
						}

						NamePart firstPart;
						NamePart secondPart;
						if (newNameCount <= startNameCount) // There are sufficient adjacent names to collapse a single or multi-part name
						{
							// Check for preceding name matches on all parts of the name
							while (index >= newNameCount)
							{
								int i = 0;
								for (; i < newNameCount; ++i)
								{
									firstPart = nameCollection[index + i];
									secondPart = nameCollection[index - newNameCount + i];
									if (!((string)firstPart).Equals((string)secondPart, firstPart.ExplicitCasing || secondPart.ExplicitCasing ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase))
									{
										break;
									}
								}
								if (i < newNameCount)
								{
									break;
								}
								nameCollection.RemoveRange(index, newNameCount);
								index -= newNameCount;
								endNameCount -= newNameCount;
							}

							// Check for following name matches on all parts of the name
							while ((endNameCount - (index + newNameCount)) >= newNameCount)
							{
								int i = 0;
								for (; i < newNameCount; ++i)
								{
									firstPart = nameCollection[index + i];
									secondPart = nameCollection[index + newNameCount + i];
									if (!((string)firstPart).Equals((string)secondPart, firstPart.ExplicitCasing || secondPart.ExplicitCasing ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase))
									{
										break;
									}
								}
								if (i < newNameCount)
								{
									break;
								}
								nameCollection.RemoveRange(index + newNameCount, newNameCount);
								index -= newNameCount;
								endNameCount -= newNameCount;
							}
						}

						if (newNameCount != 1)
						{
							// Enhance the multi-part collapse semantics by checking the
							// leading and trailing name parts.

							// Compare the parts preceding the first word
							while (index > 0 && ((string)(firstPart = nameCollection[index])).Equals((string)(secondPart = nameCollection[index - 1]), firstPart.ExplicitCasing || secondPart.ExplicitCasing ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase))
							{
								nameCollection.RemoveAt(index);
								--index;
								--endNameCount;
							}

							// Compare the parts following the last word
							while ((index + newNameCount) < endNameCount &&
								((string)(firstPart = nameCollection[index + newNameCount - 1])).Equals((string)(secondPart = nameCollection[index + newNameCount]), firstPart.ExplicitCasing || secondPart.ExplicitCasing ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase))
							{
								nameCollection.RemoveAt(index + newNameCount - 1);
								--endNameCount;
							}
						}
					}
				}
Example #2
0
				private string DoFirstLetterCase(NamePart name, bool upper, TextInfo textInfo)
				{
					string nameValue = name;
					if (string.IsNullOrEmpty(nameValue))
					{
						return nameValue;
					}
					char c = nameValue[0];
					if (upper)
					{
						c = textInfo.ToUpper(c);
					}
					else
					{
						c = textInfo.ToLower(c);
					}
					if (nameValue.Length > 1)
					{
						nameValue = c.ToString() + nameValue.Substring(1);
					}
					else
					{
						nameValue = c.ToString();
					}
					return nameValue;
				}
Example #3
0
				private void AddToNameCollection(ref NamePart singleName, ref List<NamePart> nameCollection, NamePart newNamePart)
				{
					AddToNameCollection(ref singleName, ref  nameCollection, newNamePart, -1, true);
				}
Example #4
0
				private string DoFirstWordCasing(NamePart name, NameGeneratorCasingOption casing, TextInfo textInfo)
				{
					if (name.ExplicitCasing) return name;
					switch (casing)
					{
						case NameGeneratorCasingOption.Camel:
							return TestHasAdjacentUpperCase(name) ? (string)name : DoFirstLetterCase(name, false, textInfo);
						case NameGeneratorCasingOption.Pascal:
							return TestHasAdjacentUpperCase(name) ? (string)name : DoFirstLetterCase(name, true, textInfo);
						case NameGeneratorCasingOption.Lower:
							return TestHasAdjacentUpperCase(name) ? (string)name : textInfo.ToLower(name);
						case NameGeneratorCasingOption.Upper:
							return textInfo.ToUpper(name);
					}

					return null;
				}
Example #5
0
				/// <summary>
				/// Helper for ResolveRecognizedPhrases. Returns true is parent processing is complete.
				/// </summary>
				private bool TestResolvePhraseDataForCollection(RecognizedPhraseData phraseData, ref NamePart singleName, ref List<NamePart> nameCollection, int collectionIndex, NameGenerator generator)
				{
					Debug.Assert(nameCollection != null);
					string[] matchNames = phraseData.OriginalNames;
					int matchLength = matchNames.Length;
					int i = 0;
					int firstExplicitPart = -1;
					int explicitPartCount = 0;
					for (; i < matchLength; ++i) // Note the bound on this is already verified by RecognizedPhraseData.Populate
					{
						NamePart testPart = nameCollection[collectionIndex + i];
						bool currentPartExplicit = 0 != (testPart.Options & NamePartOptions.ExplicitCasing);
						if (0 != string.Compare(testPart, matchNames[i], currentPartExplicit ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase) ||
							(matchLength == 1 && 0 != (testPart.Options & NamePartOptions.ReplacementOfSelf)))
						{
							break;
						}
						if (currentPartExplicit && firstExplicitPart == -1)
						{
							++explicitPartCount;
							firstExplicitPart = i;
						}
					}
					if (i == matchLength)
					{
						// We have a valid replacement, apply it and recurse
						string[] explicitlyCasedNames = null;
						string singleMatchName = (matchLength == 1) ? matchNames[0] : null;
						if (explicitPartCount != 0)
						{
							explicitlyCasedNames = new string[explicitPartCount];
							int nextExplicitName = 0;
							for (int j = collectionIndex + firstExplicitPart; ; ++j)
							{
								NamePart testPart = nameCollection[j];
								if (0 != (testPart.Options & NamePartOptions.ExplicitCasing))
								{
									explicitlyCasedNames[nextExplicitName] = testPart;
									if (++nextExplicitName == explicitPartCount)
									{
										break;
									}
								}
							}
							if (explicitPartCount > 1)
							{
								Array.Sort<string>(explicitlyCasedNames, StringComparer.CurrentCulture);
							}
						}
						nameCollection.RemoveRange(collectionIndex, matchLength);
						int startingCollectionSize = nameCollection.Count;
						string[] replacements = phraseData.ReplacementNames;
						for (i = 0; i < replacements.Length; ++i)
						{
							// Recognized phrases do not record casing priority and phrases are
							// generally treated as case insensitive. However, if any replacement
							// word exactly matches an explicitly cased word in the original names
							// then case the replacement as well.
							NamePartOptions options = NamePartOptions.None;
							string replacement = replacements[i];
							if (explicitlyCasedNames != null && 0 <= Array.BinarySearch<string>(explicitlyCasedNames, replacement, StringComparer.CurrentCulture))
							{
								options |= NamePartOptions.ExplicitCasing;
								if (matchLength == 1)
								{
									options |= NamePartOptions.ReplacementOfSelf;
								}
							}
							else if (singleMatchName != null && 0 == string.Compare(singleMatchName, replacement, StringComparison.CurrentCultureIgnoreCase))
							{
								options |= NamePartOptions.ExplicitCasing;
							}
							AddToNameCollection(ref singleName, ref nameCollection, new NamePart(replacement, options), collectionIndex + nameCollection.Count - startingCollectionSize, true);
						}
						ResolveRecognizedPhrases(ref singleName, ref nameCollection, generator);
						return true;
					}
					return false;
				}
Example #6
0
				private void ResolveRecognizedPhrases(ref NamePart singleName, ref List<NamePart> nameCollection, NameGenerator generator)
				{
					ORMModel model = ContextModel;
					if (model != null)
					{
						if (nameCollection != null)
						{
							int nameCount = nameCollection.Count;
							int remainingParts = nameCount;
							for (int i = 0; i < nameCount; ++i, --remainingParts)
							{
								// For each part, collection possible replacement phrases beginning with that name
								NamePart currentPart = nameCollection[i];
								RecognizedPhraseData singlePhrase = new RecognizedPhraseData();
								List<RecognizedPhraseData> phraseList = null;
								bool possibleReplacement = false;
								foreach (NameAlias alias in model.GetRecognizedPhrasesStartingWith(currentPart, generator))
								{
									RecognizedPhraseData phraseData;
									if (RecognizedPhraseData.Populate(alias, remainingParts, out phraseData))
									{
										if (phraseList == null)
										{
											possibleReplacement = true;
											if (singlePhrase.IsEmpty)
											{
												singlePhrase = phraseData;
											}
											else
											{
												phraseList = new List<RecognizedPhraseData>();
												phraseList.Add(singlePhrase);
												phraseList.Add(phraseData);
												singlePhrase = new RecognizedPhraseData();
											}
										}
										else
										{
											phraseList.Add(phraseData);
										}
									}
								}
								// If we have possible replacements, then look farther to see
								// if the multi-part phrases match. Start by searching the longest
								// match possible.
								if (possibleReplacement)
								{
									if (phraseList != null)
									{
										phraseList.Sort(delegate(RecognizedPhraseData left, RecognizedPhraseData right)
										{
											return right.OriginalNames.Length.CompareTo(left.OriginalNames.Length);
										});
										int phraseCount = phraseList.Count;
										for (int j = 0; j < phraseCount; ++j)
										{
											if (TestResolvePhraseDataForCollection(phraseList[j], ref singleName, ref nameCollection, i, generator))
											{
												return;
											}
										}
									}
									else
									{
										if (TestResolvePhraseDataForCollection(singlePhrase, ref singleName, ref nameCollection, i, generator))
										{
											return;
										}
									}
								}
							}
						}
						else if (!singleName.IsEmpty)
						{
							LocatedElement element = model.RecognizedPhrasesDictionary.GetElement(singleName);
							RecognizedPhrase phrase;
							NameAlias alias;
							if (null != (phrase = element.SingleElement as RecognizedPhrase) &&
								null != (alias = generator.FindMatchingAlias(phrase.AbbreviationCollection)))
							{
								RecognizedPhraseData phraseData;
								if (RecognizedPhraseData.Populate(alias, 1, out phraseData))
								{
									string[] replacements = phraseData.ReplacementNames;
									int replacementLength = replacements.Length;
									NamePart startingPart = singleName;
									singleName = new NamePart();
									if (replacementLength == 0)
									{
										// Highly unusual, but possible with collapsing phrases and omitted readings
										singleName = new NamePart();
									}
									else
									{
										string testForEqual = singleName;
										bool caseIfEqual = 0 != (singleName.Options & NamePartOptions.ExplicitCasing);
										singleName = new NamePart();
										if (replacementLength == 1)
										{
											string replacement = replacements[0];
											NamePartOptions options = NamePartOptions.None;
											if ((caseIfEqual && 0 == string.Compare(testForEqual, replacement, StringComparison.CurrentCulture)) ||
												(0 == string.Compare(testForEqual, replacement, StringComparison.CurrentCultureIgnoreCase)))
											{
												// Single replacement for same string
												return;
											}
											AddToNameCollection(ref singleName, ref nameCollection, new NamePart(replacement, options));
										}
										else
										{
											for (int i = 0; i < replacementLength; ++i)
											{
												string replacement = replacements[i];
												NamePartOptions options = NamePartOptions.None;
												if (caseIfEqual && 0 == string.Compare(testForEqual, replacement, StringComparison.CurrentCulture))
												{
													options |= NamePartOptions.ExplicitCasing | NamePartOptions.ReplacementOfSelf;
												}
												else if (0 == string.Compare(testForEqual, replacement, StringComparison.CurrentCultureIgnoreCase))
												{
													options |= NamePartOptions.ReplacementOfSelf;
												}
												AddToNameCollection(ref singleName, ref nameCollection, new NamePart(replacement, options));
											}
										}
										ResolveRecognizedPhrases(ref singleName, ref nameCollection, generator);
									}
									return;
								}
							}
						}
					}
				}
Example #7
0
				private string GetFinalName(NamePart singleName, List<NamePart> nameCollection, NameGenerator generator)
				{
					ResolveRecognizedPhrases(ref singleName, ref nameCollection, generator);
					NameGeneratorCasingOption casing = generator.CasingOption;
					string space = GetSpacingReplacement(generator);
					string finalName;
					if (null == nameCollection)
					{
						if (singleName.IsEmpty)
						{
							return "";
						}
						if (casing == NameGeneratorCasingOption.None)
						{
							finalName = singleName;
						}
						else
						{
							finalName = DoFirstWordCasing(singleName, casing, CultureInfo.CurrentCulture.TextInfo);
						}
					}
					else
					{
						TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;

						string name;
						if (casing == NameGeneratorCasingOption.None)
						{
							name = nameCollection[0];
						}
						else
						{
							name = DoFirstWordCasing(nameCollection[0], casing, textInfo);
						}

						//we already know there are at least two name entries, so use a string builder
						StringBuilder builder = new StringBuilder(name);

						//we already have the first entry, so mark camel as pascal
						NameGeneratorCasingOption tempCasing = casing;
						if (tempCasing == NameGeneratorCasingOption.Camel)
						{
							tempCasing = NameGeneratorCasingOption.Pascal;
						}

						//add each entry with proper spaces and casing
						int count = nameCollection.Count;
						for (int i = 1; i < count; ++i)
						{
							builder.Append(space);
							if (casing == NameGeneratorCasingOption.None)
							{
								name = nameCollection[i];
							}
							else
							{
								name = DoFirstWordCasing(nameCollection[i], tempCasing, textInfo);
							}
							builder.Append(name);
						}
						finalName = builder.ToString();
					}

					return finalName;
				}
Example #8
0
				private static int GetNameCount(ref NamePart singleName, ref List<NamePart> nameCollection)
				{
					if (singleName.IsEmpty)
					{
						return 0;
					}
					else if (nameCollection == null)
					{
						return 1;
					}
					return nameCollection.Count;
				}