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