Applying IM Text Abbreviations With ColdFusion

<cffunction
	name="ApplyTextMap"
	access="public"
	returntype="string"
	output="false"
	hint="Applies the given map (name-value structure) to the given text value.">
 
	<!--- Define arguments. --->
	<cfargument
		name="Text"
		type="string"
		required="true"
		hint="The text to which we will be applying the text map."
		/>
 
	<cfargument
		name="Map"
		type="struct"
		required="true"
		hint="The struct containing the key-value text mappings."
		/>
 
	<!--- Define the local scope. --->
	<cfset var LOCAL = StructNew() />
 
	<!--- Set up a local copy of the string. --->
	<cfset LOCAL.Text = ARGUMENTS.Text />
 
 
	<!---
		We are going to make repeated use of several Java
		objects. Therefore, let's create the static classes
		here that we can then use later for construction.
		NOTICE: We are not calling INIT as we only want the
		static version of the Java classes.
	--->
	<cfset LOCAL.StringBufferClass = CreateObject(
		"java",
		"java.lang.StringBuffer"
		) />
 
	<!--- Regular expressoin pattern class. --->
	<cfset LOCAL.PatternClass = CreateObject(
		"java",
		"java.util.regex.Pattern"
		) />
 
 
	<!---
		We are going to use a regular expression iterator
		to loop over all the values in string and perform the
		replace. No matter what, though, we have to loop over
		all values in the struct.
	--->
	<cfloop
		item="LOCAL.Key"
		collection="#ARGUMENTS.Map#">
 
		<!---
			We need to prepare the key for our search. Even
			though we are using the regular expression pattern
			matcher, we don't want the key to have any regular
			expression properties. Therefore, we need to escape
			all special characters.
		--->
		<cfset LOCAL.Key = LOCAL.Key.ReplaceAll(
			"([\+\*\{\}\[\]\(\)\?\\\$]){1}",
			"\\$1"
			) />
 
		<!---
			Create the string buffer that will hold the
			temporary results of the text changes made by
			this map-application iteration.
		--->
		<cfset LOCAL.Buffer = LOCAL.StringBufferClass.Init() />
 
		<!---
			Create the pattern we are matching. Use the
			case-insensitive flag.
		--->
		<cfset LOCAL.Pattern = LOCAL.PatternClass.Compile(
			"(?i)\b#LOCAL.Key#\b"
			) />
 
		<!--- Get the matcher for this pattern. --->
		<cfset LOCAL.Matcher = LOCAL.Pattern.Matcher(
			LOCAL.Text
			) />
 
 
		<!---
			Now that we have our matcher, let's keep iterating
			over the matcher while we can find instances of the
			pattern in the target text (that we must replace).
		--->
		<cfloop condition="LOCAL.Matcher.Find()">
 
			<!---
				Replace the current match with value in the text
				map. When performing the match, we have to make
				sure that it has no regular expression parts.
			--->
			<cfset LOCAL.Matcher.AppendReplacement(
				LOCAL.Buffer,
				ToString(
					ARGUMENTS.Map[ LOCAL.Matcher.Group() ]
					).ReplaceAll(
						"(\\|\$){1}",
						"\\$1"
						)
				) />
 
		</cfloop>
 
 
		<!---
			We have replaced all instances of the given
			pattern. Now, just append what ever we didn't
			already put in the buffer.
		--->
		<cfset LOCAL.Matcher.AppendTail(
			LOCAL.Buffer
			) />
 
 
		<!---
			Now that we have completely replaced the current
			term in the text map, let's save the results back
			into the local text result for the next iteration.
		--->
		<cfset LOCAL.Text = LOCAL.Buffer.ToString() />
 
	</cfloop>
 
 
	<!--- Return the modified arguments. --->
	<cfreturn LOCAL.Text />
</cffunction>

For Cut-and-Paste