001/*-
002 * #%L
003 * Smile CDR - CDR
004 * %%
005 * Copyright (C) 2016 - 2025 Smile CDR, Inc.
006 * %%
007 * All rights reserved.
008 * #L%
009 */
010package ca.cdr.api.hl7v2.util;
011
012import ca.uhn.hl7v2.model.primitive.FormattedTextEncoder;
013import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter;
014import com.vladsch.flexmark.util.data.MutableDataSet;
015import org.apache.commons.lang3.StringUtils;
016
017/**
018 * <p>Utility class for encoding the following character sequences contained in HL7v2 FT (formatted text) fields:</p>
019 * <ul>
020 *      <li>\h\ \n\ - Bold text highlighting</li>
021 *              <li>\.br\ - Line break</li>
022 *              <li>\.ce\ - Center line</li>
023 *              <li>\.fi\ - Fill mode (word wrap)</li>
024 *              <li>\.nf\ - No-fill mode (no wrap)</li>
025 *              <li>\.in X\ - Indent by X spaces</li>
026 *              <li>\.ti X\ - Temporarily indent by X spaces</li>
027 *              <li>\.sk X\ - Skip X spaces to the right</li>
028 *              <li>\.sp X\ - Skip X vertical spaces</li>
029 * </ul>
030 * <p>See {@link OutputFormat} for available output formats.</p>
031 */
032public final class Hl7v2FormattedTextEncoder {
033
034        /**
035         * Output formats for {@link Hl7v2FormattedTextEncoder}
036         */
037        public enum OutputFormat {
038                XHTML,
039                MARKDOWN
040        }
041
042        private Hl7v2FormattedTextEncoder() {
043                // Utility class
044        }
045
046        /**
047         * Encodes a String with HL7v2 FT character sequences to the specified output format
048         * @param theFormattedText - A String containing HL7v2 FT character sequences to be encoded
049         * @param theOutputFormat - The {@link OutputFormat}
050         * @return A String with HL7v2 FT character sequences encoded
051         */
052        public static String encode(String theFormattedText, OutputFormat theOutputFormat) {
053                if (StringUtils.isBlank(theFormattedText)) {
054                        return "";
055                }
056
057                FormattedTextEncoder encoder = FormattedTextEncoder.getInstanceHtml();
058                String htmlResult = encoder.encode(theFormattedText);
059
060                return switch (theOutputFormat) {
061                        case XHTML -> htmlResult;
062                        case MARKDOWN -> convertXhtmlToMarkdown(htmlResult);
063                        default -> throw new IllegalArgumentException("Cannot handle output format: %s".formatted(theOutputFormat));
064                };
065        }
066
067        private static String convertXhtmlToMarkdown(String theXhtml) {
068                MutableDataSet options = new MutableDataSet()
069                                .set(FlexmarkHtmlConverter.BR_AS_PARA_BREAKS, false)
070                                .set(FlexmarkHtmlConverter.BR_AS_EXTRA_BLANK_LINES, false);
071
072                return FlexmarkHtmlConverter.builder(options).build().convert(theXhtml).trim();
073        }
074}