001package org.apache.commons.jcs3.log;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements. See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache license, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License. You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the license for the specific language governing permissions and
017 * limitations under the license.
018 */
019
020import java.text.MessageFormat;
021import java.util.IllegalFormatException;
022import java.util.function.Supplier;
023import java.util.stream.Stream;
024
025/**
026 * Handles messages that consist of a format string conforming to
027 * java.text.MessageFormat. (Borrowed from log4j2)
028 */
029public class MessageFormatter
030{
031    private final String messagePattern;
032    private final transient Object[] parameters;
033    private transient String formattedMessage;
034    private transient Throwable throwable;
035
036    /**
037     * Constructs a message formatter.
038     *
039     * @param messagePattern
040     *            the pattern for this message format
041     * @param parameters
042     *            The objects to format
043     */
044    public MessageFormatter(final String messagePattern, final Object... parameters)
045    {
046        this.messagePattern = messagePattern;
047        this.parameters = parameters;
048        final int length = parameters == null ? 0 : parameters.length;
049        if (length > 0 && parameters[length - 1] instanceof Throwable)
050        {
051            this.throwable = (Throwable) parameters[length - 1];
052        }
053    }
054
055    /**
056     * Constructs a message formatter.
057     *
058     * @param messagePattern
059     *            the pattern for this message format
060     * @param paramSuppliers
061     *            An array of functions, which when called, produce the desired
062     *            log message parameters.
063     */
064    public MessageFormatter(final String messagePattern, final Supplier<?>... paramSuppliers)
065    {
066        this.messagePattern = messagePattern;
067        this.parameters = Stream.of(paramSuppliers)
068                            .map(Supplier::get)
069                            .toArray();
070
071        final int length = parameters.length;
072        if (length > 0 && parameters[length - 1] instanceof Throwable)
073        {
074            this.throwable = (Throwable) parameters[length - 1];
075        }
076    }
077
078    /**
079     * Returns the formatted message.
080     *
081     * @return the formatted message.
082     */
083    public String getFormattedMessage()
084    {
085        if (formattedMessage == null)
086        {
087            formattedMessage = formatMessage(messagePattern, parameters);
088        }
089        return formattedMessage;
090    }
091
092    protected String formatMessage(final String msgPattern, final Object... args)
093    {
094        try
095        {
096            final MessageFormat temp = new MessageFormat(msgPattern);
097            return temp.format(args);
098        }
099        catch (final IllegalFormatException ife)
100        {
101            return msgPattern;
102        }
103    }
104
105    @Override
106    public String toString()
107    {
108        return getFormattedMessage();
109    }
110
111    /**
112     * Return the throwable passed to the Message.
113     *
114     * @return the Throwable.
115     */
116    public Throwable getThrowable()
117    {
118        return throwable;
119    }
120
121    /**
122     * Return true, if the parameters list contains a Throwable.
123     *
124     * @return true, if the parameters list contains a Throwable.
125     */
126    public boolean hasThrowable()
127    {
128        return throwable != null;
129    }
130}