ca.uhn.hl7v2.model.primitive.FormattedTextEncoder Maven / Gradle / Ivy
package ca.uhn.hl7v2.model.primitive;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* Provides methods to convert between HL7 Formatted Text encoding (See Chapter
* 2.7) and other encoding schemes.
*
*
* For now, only {@link #getInstanceHtml() HTML encoding} is supported, but others may be added.
*
*
* Note that this class is not threadsafe! Always use a new instance
* (from a factory method) for each invocation.
*
*
* @author James Agnew
* @see AbstractTextPrimitive
*/
public class FormattedTextEncoder {
private StringBuilder myBuffer;
private int myInBold;
private boolean myInCenter;
/**
* Use factory methods to instantiate this class
*/
private FormattedTextEncoder() {
super();
}
private void addLt() {
myBuffer.append("<");
}
private void addGt() {
myBuffer.append(">");
}
private void addAmpersand() {
myBuffer.append("&");
}
private void addBreak() {
myBuffer.append("
");
}
private void addEndNoBreak() {
myBuffer.append("");
}
private void addHighAscii(char nextChar) {
myBuffer.append("");
myBuffer.append((int) nextChar);
myBuffer.append(";");
}
private void addSpace() {
myBuffer.append(" ");
}
private void addStartCenter() {
myBuffer.append("");
}
private void addStartNoBreak() {
myBuffer.append("");
}
private void closeCenterIfNeeded() {
if (myInCenter) {
myBuffer.append(" ");
}
}
/**
* Convert the input string containing FT encoding strings (\.br\, \.sp XX\,
* etc.) into the appropriate output type for this encoder (currently HTML)
*
* @param theInput
* The input string
* @return An encoded version of the input string
*/
public String encode(String theInput) {
if (theInput == null) {
return null;
}
myBuffer = new StringBuilder(theInput.length() + 20);
boolean myAtStartOfLine = true;
myInCenter = false;
boolean myWordWrap = true;
int myCurrentLineOffset = 0;
int myTemporaryIndent = 0;
int myIndent = 0;
boolean myNeedBreakBeforeNextText = false;
boolean myInDiv = false;
myInBold = 0;
for (int i = 0; i < theInput.length(); i++) {
char nextChar = theInput.charAt(i);
boolean handled = true;
switch (nextChar) {
case '\\':
int theStart = i + 1;
int numericArgument = Integer.MIN_VALUE;
int offsetIncludingNumericArgument = 0;
String nextFourChars = theInput.substring(theStart, Math.min(theInput.length(), theStart + 4)).toLowerCase();
if (theInput.length() >= theStart + 5) {
char sep = theInput.charAt(i + 4);
if (theInput.charAt(i + 1) == '.' && (sep == ' ' || sep == '-' || sep == '+')) {
String nextThirtyChars = theInput.substring(theStart + 3, Math.min(theInput.length(), theStart + 30));
Matcher m = Pattern.compile("^([ +-]?[0-9]+)\\\\").matcher(nextThirtyChars);
if (m.find()) {
String group = m.group(1);
offsetIncludingNumericArgument = group.length() + 4;
group = group.replace('+', ' ').trim();
numericArgument = Integer.parseInt(group);
}
}
}
if (nextFourChars.equals(".br\\")) {
closeCenterIfNeeded();
if (myNeedBreakBeforeNextText) {
addBreak();
}
myNeedBreakBeforeNextText = true;
i += 4;
myAtStartOfLine = true;
myInCenter = false;
myCurrentLineOffset = 0;
} else if (nextFourChars.startsWith("h\\")) {
startBold();
i += 2;
} else if (nextFourChars.startsWith("n\\")) {
endBold();
i += 2;
} else if (nextFourChars.startsWith(".in") && myAtStartOfLine && numericArgument != Integer.MIN_VALUE) {
myIndent = numericArgument;
myTemporaryIndent = 0;
i += offsetIncludingNumericArgument;
} else if (nextFourChars.startsWith(".ti") && myAtStartOfLine && numericArgument != Integer.MIN_VALUE) {
myTemporaryIndent = numericArgument;
i += offsetIncludingNumericArgument;
} else if (nextFourChars.equals(".ce\\")) {
closeCenterIfNeeded();
if (!myAtStartOfLine) {
addBreak();
}
addStartCenter();
i += 4;
myAtStartOfLine = false;
myInCenter = true;
} else if (nextFourChars.equals(".fi\\")) {
if (!myWordWrap) {
addEndNoBreak();
myWordWrap = true;
}
i += 4;
} else if (nextFourChars.equals(".nf\\")) {
if (myWordWrap) {
addStartNoBreak();
myWordWrap = false;
}
i += 4;
} else if (nextFourChars.startsWith(".sp")) {
if (nextFourChars.equals(".sp\\")) {
numericArgument = 1;
i += 4;
} else if (numericArgument != -1) {
i += offsetIncludingNumericArgument;
}
if (numericArgument > 0) {
for (int j = 0; j < numericArgument; j++) {
addBreak();
}
for (int j = 0; j < myCurrentLineOffset; j++) {
addSpace();
}
} else if (numericArgument == Integer.MIN_VALUE) {
handled = false;
}
} else if (nextFourChars.equals(".sk ") && numericArgument >= 0) {
for (int j = 0; j < numericArgument; j++) {
addSpace();
}
i += offsetIncludingNumericArgument;
} else {
handled = false;
}
break;
default:
handled = false;
}
if (!handled) {
if (myAtStartOfLine) {
int thisLineIndent = Math.max(0, myIndent + myTemporaryIndent);
if (myNeedBreakBeforeNextText) {
if (myInDiv) {
myBuffer.append("