Skip to content

TitleCase

A stateless, rules-driven text-casing engine that normalizes legacy uppercase-stored text into display-ready title case while preserving original delimiter characters. The class enforces a comprehensive set of recognition lists (acronyms, minor words, irregular spellings, ordinal suffixes) and applies deterministic per-token casing rules to produce consistently formatted names, addresses, and descriptions. All members are shared/static; the class holds no instance state, making it thread-safe and suitable for high-volume formatting workloads.

Purpose

  • Normalize free-form name/address/description text (typically all-caps legacy data) into display-ready title case by applying rules-driven per-token casing while preserving all original delimiter characters in their original positions.
  • Enforce consistent casing for recognized acronyms (e.g. LLC, PhD, directionals, state codes), minor words (e.g. is, the, of), and irregular spellings (e.g. LaCombe).
  • Support optional features like capital-letter padding (expanding run-together identifiers) and ordinal suffix normalization (e.g. 52nd).

Context

  • Namespace: SAIF.Business.Utilities
  • Assembly/package: SAIF.Business.Utilities.dll
  • Base class: System.Object

Public members

Member Signature Purpose
ToTitleCase Public Shared Function ToTitleCase(ByVal inString As String) As String Entry point for title-casing; sole public member of the class. Accepts a free-form string and returns the cased result. Applies all recognition lists and delimiter preservation. Returns input unchanged if Nothing or whitespace-only.

Private implementation members (documented for control flow)

The following members implement the title-casing logic and are not part of the public surface:

Member Signature Role
UpperCaseWordList Private Shared ReadOnly array of String Recognition list for acronyms and abbreviations (e.g. SAIF, LLC, PhD, state codes, roman numerals) — words matching this list are fully upper-cased
LowerCaseWordList Private Shared ReadOnly array of String Recognition list for minor words (e.g. is, in, the, of, on, and, de) — words matching this list are fully lower-cased (unless BR-011)
MixedCaseWordList Private Shared ReadOnly array of String Recognition list for words requiring irregular mixed-case casing (e.g. PhD, LaCombe) — words matching this list (case-insensitive) are replaced with their canonical form
MixedCasePrefixList Private Shared ReadOnly array of String Recognition list for surname prefixes (Mc, O') — handled specially to retain prefix casing and proper-case the remainder
MixedCaseSuffixList Private Shared ReadOnly array of String Recognition list for possessive/exact suffixes ('s, 't) — normalized to canonical lower-case form after reassembly
NumberSuffixes Private Shared ReadOnly array of String Recognition list for ordinal suffixes (st, nd, rd, th) — used to identify and lowercase numeric ordinal tokens
TitleCaseSingleWord Private Shared Function (ByVal word As String) As String Apply casing rules to a single token; implements the rule-precedence chain (BR-004 through BR-009 then BR-012)
ReassembleString (overload 1) Private Shared Function (ByVal splitWords As String(), ByVal inSourceString As String) As String Rebuild the cased string with delimiter characters at their original positions; entry point for recursion
ReassembleString (overload 2) Private Shared Function (ByVal splitWords As String(), ByVal inSourceString As String, ByVal currentWordIndex As Integer, ByVal currentCharIndex As Integer, ByVal result As StringBuilder) As String Recursive helper that walks through source character positions, inserting delimiters and cased word tokens
ApplyExactSuffixList Private Shared Function (ByVal inWord As String) As String Normalize trailing suffixes (e.g. 's) to canonical casing using MixedCaseSuffixList
HasNumberSuffix Private Shared Function (ByVal inWord As String) As Boolean Guard: return true if the word ends with a recognized ordinal suffix and the preceding portion is purely numeric
GetNumberSuffixParts Private Shared Function (ByVal inWord As String) As Tuple(Of String, String) Decompose an ordinal token into numeric and suffix parts
ContainsOnlyNumericCharacters Public Function (ByVal Target As String) As Boolean Note: This is exposed as a public extension method via TitleCaseExtensions — Guard for ordinal suffix detection; confirms a token is purely digits (non-null, non-blank, no \D match)

Behavioral notes

  • Statelessness: All members are Shared; the class holds no instance state, so calls are side-effect free and thread-safe*.
  • Recursion in reassembly: ReassembleString is recursive; recursion depth scales with word count. For heavily-delimited strings (e.g. file paths with many slashes), deep recursion is possible*.
  • Delimiter position mapping: The reassembly algorithm assumes an exact correspondence between split-word count and delimiter positions in the source string. Malformed input whose delimiter pattern is not perfectly reconstructible can cause IndexOutOfRangeException**.
  • Rule precedence within TitleCaseSingleWord: The per-word casing rules are applied in strict order — BR-004, BR-005, BR-006, BR-007, BR-008, BR-009, then BR-012 as a post-adjustment. The first matching branch wins; subsequent branches are never evaluated*.
  • First-character override: BR-011 forces the first character of the final result to upper case, even if it matches a minor-word rule.
  • StrConv usage: The ToProperCase extension method (exposed via TitleCaseExtensions) uses VB.NET's StrConv(..., VbStrConv.ProperCase) as a fallback when no specific rule matches. This VB runtime function may behave differently across frameworks and locales*.

Constraints and usage notes

  • The public ToTitleCase method is stateless and can be called concurrently without synchronization.
  • Input strings with multi-byte or accented characters are handled by the regex and string routines; whether behavior matches intent for non-ASCII scripts is unverified*.
  • The regex pattern [^\d\w] (used for splitting) includes underscores as word characters (\w in .NET includes [a-zA-Z0-9_]); strings with underscores will not be split on underscore characters, so Policy_Name remains a single token*.
  • Recognition lists are hard-coded and immutable; adding a new acronym or exception requires a code change and redeploy, not a configuration change.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • SAIF.Business.Utilities/TitleCase.vb
  • SAIF.Business.Utilities/SAIF.Business.Utilities.vbproj