001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2005-2005 Julian Hyde
008// Copyright (C) 2005-2011 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.recorder;
012
013import mondrian.resource.MondrianResource;
014
015import java.util.ArrayList;
016import java.util.List;
017
018/**
019 * Abstract implemention of the {@link MessageRecorder} interface.
020 *
021 * @author Richard M. Emberson
022 */
023public abstract class AbstractRecorder implements MessageRecorder {
024
025    /**
026     * Helper method to format a message and write to logger.
027     */
028    public static void logMessage(
029        final String context,
030        final String msg,
031        final MsgType msgType,
032        final org.apache.log4j.Logger logger)
033    {
034        StringBuilder buf = new StringBuilder(64);
035        buf.append(context);
036        buf.append(": ");
037        buf.append(msg);
038
039        switch (msgType) {
040        case INFO:
041            logger.info(buf.toString());
042            break;
043        case WARN:
044            logger.warn(buf.toString());
045            break;
046        case ERROR:
047            logger.error(buf.toString());
048            break;
049        default:
050            logger.warn(
051                "Unknown message type enum \""
052                + msgType + "\" for message: " + buf.toString());
053        }
054    }
055
056    enum MsgType {
057        INFO,
058        WARN,
059        ERROR
060    }
061
062    public static final int DEFAULT_MSG_LIMIT = 10;
063
064    private final int errorMsgLimit;
065    private final List<String> contexts;
066    private int errorMsgCount;
067    private int warningMsgCount;
068    private int infoMsgCount;
069    private String contextMsgCache;
070    private long startTime;
071
072    protected AbstractRecorder() {
073        this(DEFAULT_MSG_LIMIT);
074    }
075
076    protected AbstractRecorder(final int errorMsgLimit) {
077        this.errorMsgLimit = errorMsgLimit;
078        this.contexts = new ArrayList<String>();
079        this.startTime = System.currentTimeMillis();
080    }
081
082    /**
083     * Resets this MessageRecorder.
084     */
085    public void clear() {
086        errorMsgCount = 0;
087        warningMsgCount = 0;
088        infoMsgCount = 0;
089        contextMsgCache = null;
090        contexts.clear();
091        this.startTime = System.currentTimeMillis();
092    }
093
094    public long getStartTimeMillis() {
095        return this.startTime;
096    }
097
098    public long getRunTimeMillis() {
099        return (System.currentTimeMillis() - this.startTime);
100    }
101
102    public boolean hasInformation() {
103        return (infoMsgCount > 0);
104    }
105
106    public boolean hasWarnings() {
107        return (warningMsgCount > 0);
108    }
109
110    public boolean hasErrors() {
111        return (errorMsgCount > 0);
112    }
113
114    public int getInfoCount() {
115        return infoMsgCount;
116    }
117
118    public int getWarningCount() {
119        return warningMsgCount;
120    }
121
122    public int getErrorCount() {
123        return errorMsgCount;
124    }
125
126    public String getContext() {
127        // heavy weight
128        if (contextMsgCache == null) {
129            final StringBuilder buf = new StringBuilder();
130            int k = 0;
131            for (String name : contexts) {
132                if (k++ > 0) {
133                    buf.append(':');
134                }
135                buf.append(name);
136            }
137            contextMsgCache = buf.toString();
138        }
139        return contextMsgCache;
140    }
141
142    public void pushContextName(final String name) {
143        // light weight
144        contexts.add(name);
145        contextMsgCache = null;
146    }
147
148    public void popContextName() {
149        // light weight
150        contexts.remove(contexts.size() - 1);
151        contextMsgCache = null;
152    }
153
154    public void throwRTException() throws RecorderException {
155        if (hasErrors()) {
156            final String errorMsg =
157                MondrianResource.instance().ForceMessageRecorderError.str(
158                    getContext(),
159                    errorMsgCount);
160            throw new RecorderException(errorMsg);
161        }
162    }
163
164    public void reportError(final Exception ex)
165        throws RecorderException
166    {
167        reportError(ex, null);
168    }
169
170    public void reportError(final Exception ex, final Object info)
171        throws RecorderException
172    {
173        reportError(ex.toString(), info);
174    }
175
176    public void reportError(final String msg)
177        throws RecorderException
178    {
179        reportError(msg, null);
180    }
181
182    public void reportError(final String msg, final Object info)
183        throws RecorderException
184    {
185        errorMsgCount++;
186        recordMessage(msg, info, MsgType.ERROR);
187
188        if (errorMsgCount >= errorMsgLimit) {
189            final String errorMsg =
190                MondrianResource.instance().TooManyMessageRecorderErrors.str(
191                    getContext(),
192                    errorMsgCount);
193            throw new RecorderException(errorMsg);
194        }
195    }
196
197    public void reportWarning(final String msg) {
198        reportWarning(msg, null);
199    }
200
201    public void reportWarning(final String msg, final Object info) {
202        warningMsgCount++;
203        recordMessage(msg, info, MsgType.WARN);
204    }
205
206    public void reportInfo(final String msg) {
207        reportInfo(msg, null);
208    }
209
210    public void reportInfo(final String msg, final Object info) {
211        infoMsgCount++;
212        recordMessage(msg, info, MsgType.INFO);
213    }
214
215    /**
216     * Handles a message.
217     * Classes implementing this abstract class must provide an implemention
218     * of this method; it receives all warning/error messages.
219     *
220     * @param msg the error or warning message.
221     * @param info the information Object which might be null.
222     * @param msgType one of the message type enum values
223     */
224    protected abstract void recordMessage(
225        String msg,
226        Object info,
227        MsgType msgType);
228}
229
230// End AbstractRecorder.java