public String format()

in endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/MonolineFormatter.java [691:845]


    public String format(final LogRecord record) {
        boolean faint = false;                      // Whether to use faint text for level < INFO.
        String emphasisStart = "";                  // ANSI escape sequence for bold text if we use it.
        String emphasisEnd   = "";                  // ANSI escape sequence for stopping bold text if we use it.
        final Level level = record.getLevel();
        synchronized (buffer) {
            final boolean colored = (colors != null);
            if (colored && level.intValue() >= LEVEL_THRESHOLD.intValue()) {
                emphasisStart = X364.BOLD.sequence();
                emphasisEnd   = X364.NORMAL.sequence();
                faint         = faintSupported;
            }
            buffer.setLength(header.length());
            /*
             * Append the time (e.g. "00:00:12.365"). The time pattern can be set either
             * programmatically by a call to `setTimeFormat(…)`, or in logging.properties
             * file with the "org.apache.sis.util.logging.MonolineFormatter.time" property.
             */
            if (timeFormat != null) {
                Date time = new Date(Math.max(0, record.getMillis() - startMillis));
                timeFormat.format(time, buffer, new FieldPosition(0));
                buffer.append(' ');
            }
            /*
             * Append the level (e.g. "FINE"). We do not provide the option to turn level off for now.
             * This level will be formatted with a colorized background if ANSI escape sequences are enabled.
             */
            int margin = buffer.length();
            String levelColor = "", levelReset = "";
            if (SHOW_LEVEL) {
                if (colored) {
                    levelColor = colorAt(level);
                    levelReset = X364.BACKGROUND_DEFAULT.sequence();
                }
                final int offset = buffer.append(levelColor).append(emphasisStart).length();
                final int length = buffer.append(level.getLocalizedName()).length() - offset;
                buffer.append(emphasisEnd).append(CharSequences.spaces(levelWidth - length));
                margin += buffer.length() - emphasisEnd.length() - offset;
                buffer.append(levelReset).append(' ');
            }
            /*
             * Append the logger name or source class name, in long of short form.
             * The name may be formatted in bold characters if ANSI escape sequences are enabled.
             */
            String source;
            switch (sourceFormat) {
                case LOGGER_SHORT: // Fall through
                case LOGGER_LONG:  source = record.getLoggerName(); break;
                case METHOD:       // Fall through
                case CLASS_SHORT:  // Fall through
                case CLASS_LONG:   source = record.getSourceClassName(); break;
                default:           source = null; break;
            }
            if (source != null) {
                switch (sourceFormat) {
                    case METHOD:       // Fall through
                    case LOGGER_SHORT: // Fall through
                    case CLASS_SHORT: {
                        // Works even if there is no '.' since we get -1 as index.
                        source = source.substring(source.lastIndexOf('.') + 1);
                        break;
                    }
                }
                if (sourceFormat == METHOD) {
                    source = source + '.' + record.getSourceMethodName();
                }
                buffer.append(emphasisStart).append('[').append(source).append(']').append(emphasisEnd).append(' ');
            }
            /*
             * Now prepare the LineAppender for the message. We set a line separator prefixed by some
             * number of spaces in order to align message body on the column after the level name.
             */
            String bodyLineSeparator = writer.getLineSeparator();
            final String lineSeparator = System.lineSeparator();
            if (bodyLineSeparator.length() != lineSeparator.length() + margin + 1) {
                if (CONTINUATION_MARGIN != 0) {
                    final int highlight = Math.min(CONTINUATION_MARGIN, margin);
                    bodyLineSeparator = lineSeparator
                            + levelColor + Strings.CONTINUATION_MARK + CharSequences.spaces(highlight - 1)
                            + levelReset + CharSequences.spaces(margin - highlight + 1);
                } else {
                    bodyLineSeparator = lineSeparator;
                }
                writer.setLineSeparator(bodyLineSeparator);
            }
            if (faint) {
                buffer.append(X364.FAINT.sequence());
            }
            final Throwable exception = record.getThrown();
            String message = formatMessage(record);
            int maximalLength = Integer.MAX_VALUE;
            int length = 0;
            if (message != null) {
                length = CharSequences.skipTrailingWhitespaces(message, 0, message.length());
                if (maximalLineLength != null) {
                    maximalLength = maximalLineLength.getAsInt();
                }
            }
            /*
             * Up to this point, we wrote directly in the StringBuilder for performance reasons.
             * Now for the message part, we need to use the LineAppender in order to replace EOL
             * and tabulations.
             */
            writer.setMaximalLineLength(Math.max(maximalLength - margin - 3, 10));
            writer.setCurrentLineLength(X364.lengthOfPlain(buffer, 0, buffer.length()));
            try {
                if (message != null) {
                    writer.append(message, 0, length);
                }
                if (exception != null) {
                    if (message != null) {
                        writer.append("\nCaused by: ");     // LineAppender will replace '\n' by the system EOL.
                    }
                    if (level.intValue() >= LEVEL_THRESHOLD.intValue()) {
                        exception.printStackTrace(printer);
                    } else {
                        printAbridged(exception, writer, record.getLoggerName(),
                                record.getSourceClassName(), record.getSourceMethodName());
                    }
                }
                writer.clear();
                writer.flush();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            /*
             * We wrote the main content, but maybe with some extra lines. Trim the last lines by skipping white spaces
             * and line separator (EOL). If the `bodyLineSeparator` margin is found immediately before the white spaces
             * and EOL that we skipped, we repeat this process until we find at least one non-white character after the
             * `bodyLineSeparator`.
             */
            int lastMargin = buffer.length();
            do {
                length = CharSequences.skipTrailingWhitespaces(buffer, 0, lastMargin);
                lastMargin = buffer.lastIndexOf(bodyLineSeparator);
                buffer.setLength(length);
                length -= lastMargin;
            } while (length > 0 && length <= bodyLineSeparator.length());
            if (faint) {
                buffer.append(X364.NORMAL.sequence());
            }
            /*
             * At this point we finished to write the message, except for the final line separator.
             * If the message spans more than one line, there is CONTINUATION_MARK characters in the
             * margin. Replace the last occurrence of those characters by CONTINUATION_END.
             */
            lastMargin = CharSequences.indexOf(buffer, Strings.CONTINUATION_MARK,
                            lastMargin + lineSeparator.length(),
                            lastMargin + bodyLineSeparator.length());
            if (lastMargin >= 0) {
                buffer.setCharAt(lastMargin, Strings.CONTINUATION_END);
            }
            return buffer.append(lineSeparator).toString();
        }
    }