001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.common.collection;
017
018import java.util.Collections;
019import java.util.EnumSet;
020import java.util.Iterator;
021import java.util.List;
022import org.modeshape.common.collection.Problem.Status;
023import org.modeshape.common.function.Consumer;
024import org.modeshape.common.i18n.I18n;
025import org.modeshape.common.logging.Logger;
026import org.modeshape.common.logging.Logger.Level;
027
028/**
029 * A list of problems for some execution context. The problems will be {@link #iterator() returned} in the order in which they
030 * were encountered (although this cannot be guaranteed in contexts involving multiple threads or processes).
031 */
032public abstract class AbstractProblems implements Problems {
033    private static final long serialVersionUID = 1L;
034
035    protected static final List<Problem> EMPTY_PROBLEMS = Collections.emptyList();
036
037    @Override
038    public void addError( I18n message,
039                          Object... params ) {
040        addProblem(new Problem(Problem.Status.ERROR, Problem.DEFAULT_CODE, message, params, null, null, null));
041    }
042
043    @Override
044    public void addError( Throwable throwable,
045                          I18n message,
046                          Object... params ) {
047        addProblem(new Problem(Problem.Status.ERROR, Problem.DEFAULT_CODE, message, params, null, null, throwable));
048    }
049
050    @Override
051    public void addError( String resource,
052                          String location,
053                          I18n message,
054                          Object... params ) {
055        addProblem(new Problem(Problem.Status.ERROR, Problem.DEFAULT_CODE, message, params, resource, location, null));
056    }
057
058    @Override
059    public void addError( Throwable throwable,
060                          String resource,
061                          String location,
062                          I18n message,
063                          Object... params ) {
064        addProblem(new Problem(Problem.Status.ERROR, Problem.DEFAULT_CODE, message, params, resource, location, throwable));
065    }
066
067    @Override
068    public void addError( int code,
069                          I18n message,
070                          Object... params ) {
071        addProblem(new Problem(Problem.Status.ERROR, code, message, params, null, null, null));
072    }
073
074    @Override
075    public void addError( Throwable throwable,
076                          int code,
077                          I18n message,
078                          Object... params ) {
079        addProblem(new Problem(Problem.Status.ERROR, code, message, params, null, null, throwable));
080    }
081
082    @Override
083    public void addError( int code,
084                          String resource,
085                          String location,
086                          I18n message,
087                          Object... params ) {
088        addProblem(new Problem(Problem.Status.ERROR, code, message, params, resource, location, null));
089    }
090
091    @Override
092    public void addError( Throwable throwable,
093                          int code,
094                          String resource,
095                          String location,
096                          I18n message,
097                          Object... params ) {
098        addProblem(new Problem(Problem.Status.ERROR, code, message, params, resource, location, throwable));
099    }
100
101    @Override
102    public void addWarning( I18n message,
103                            Object... params ) {
104        addProblem(new Problem(Problem.Status.WARNING, Problem.DEFAULT_CODE, message, params, null, null, null));
105    }
106
107    @Override
108    public void addWarning( Throwable throwable,
109                            I18n message,
110                            Object... params ) {
111        addProblem(new Problem(Problem.Status.WARNING, Problem.DEFAULT_CODE, message, params, null, null, throwable));
112    }
113
114    @Override
115    public void addWarning( String resource,
116                            String location,
117                            I18n message,
118                            Object... params ) {
119        addProblem(new Problem(Problem.Status.WARNING, Problem.DEFAULT_CODE, message, params, resource, location, null));
120    }
121
122    @Override
123    public void addWarning( Throwable throwable,
124                            String resource,
125                            String location,
126                            I18n message,
127                            Object... params ) {
128        addProblem(new Problem(Problem.Status.WARNING, Problem.DEFAULT_CODE, message, params, resource, location, throwable));
129    }
130
131    @Override
132    public void addWarning( int code,
133                            I18n message,
134                            Object... params ) {
135        addProblem(new Problem(Problem.Status.WARNING, code, message, params, null, null, null));
136    }
137
138    @Override
139    public void addWarning( Throwable throwable,
140                            int code,
141                            I18n message,
142                            Object... params ) {
143        addProblem(new Problem(Problem.Status.WARNING, code, message, params, null, null, throwable));
144    }
145
146    @Override
147    public void addWarning( int code,
148                            String resource,
149                            String location,
150                            I18n message,
151                            Object... params ) {
152        addProblem(new Problem(Problem.Status.WARNING, code, message, params, resource, location, null));
153    }
154
155    @Override
156    public void addWarning( Throwable throwable,
157                            int code,
158                            String resource,
159                            String location,
160                            I18n message,
161                            Object... params ) {
162        addProblem(new Problem(Problem.Status.WARNING, code, message, params, resource, location, throwable));
163    }
164
165    @Override
166    public void addInfo( I18n message,
167                         Object... params ) {
168        addProblem(new Problem(Problem.Status.INFO, Problem.DEFAULT_CODE, message, params, null, null, null));
169    }
170
171    @Override
172    public void addInfo( Throwable throwable,
173                         I18n message,
174                         Object... params ) {
175        addProblem(new Problem(Problem.Status.INFO, Problem.DEFAULT_CODE, message, params, null, null, throwable));
176    }
177
178    @Override
179    public void addInfo( String resource,
180                         String location,
181                         I18n message,
182                         Object... params ) {
183        addProblem(new Problem(Problem.Status.INFO, Problem.DEFAULT_CODE, message, params, resource, location, null));
184    }
185
186    @Override
187    public void addInfo( Throwable throwable,
188                         String resource,
189                         String location,
190                         I18n message,
191                         Object... params ) {
192        addProblem(new Problem(Problem.Status.INFO, Problem.DEFAULT_CODE, message, params, resource, location, throwable));
193    }
194
195    @Override
196    public void addInfo( int code,
197                         I18n message,
198                         Object... params ) {
199        addProblem(new Problem(Problem.Status.INFO, code, message, params, null, null, null));
200    }
201
202    @Override
203    public void addInfo( Throwable throwable,
204                         int code,
205                         I18n message,
206                         Object... params ) {
207        addProblem(new Problem(Problem.Status.INFO, code, message, params, null, null, throwable));
208    }
209
210    @Override
211    public void addInfo( int code,
212                         String resource,
213                         String location,
214                         I18n message,
215                         Object... params ) {
216        addProblem(new Problem(Problem.Status.INFO, code, message, params, resource, location, null));
217    }
218
219    @Override
220    public void addInfo( Throwable throwable,
221                         int code,
222                         String resource,
223                         String location,
224                         I18n message,
225                         Object... params ) {
226        addProblem(new Problem(Problem.Status.INFO, code, message, params, resource, location, throwable));
227    }
228
229    @Override
230    public boolean hasProblems() {
231        return getProblems().size() > 0;
232    }
233
234    @Override
235    public boolean hasErrors() {
236        for (Problem problem : this.getProblems()) {
237            if (problem.getStatus() == Problem.Status.ERROR) return true;
238        }
239        return false;
240    }
241
242    @Override
243    public boolean hasWarnings() {
244        for (Problem problem : this.getProblems()) {
245            if (problem.getStatus() == Problem.Status.WARNING) return true;
246        }
247        return false;
248    }
249
250    @Override
251    public boolean hasInfo() {
252        for (Problem problem : this.getProblems()) {
253            if (problem.getStatus() == Problem.Status.INFO) return true;
254        }
255        return false;
256    }
257
258    @Override
259    public boolean isEmpty() {
260        return getProblems().isEmpty();
261    }
262
263    @Override
264    public int errorCount() {
265        int count = 0;
266        for (Problem problem : getProblems()) {
267            if (problem.getStatus() == Problem.Status.ERROR) ++count;
268        }
269        return count;
270    }
271
272    @Override
273    public int problemCount() {
274        return getProblems().size();
275    }
276
277    @Override
278    public int warningCount() {
279        int count = 0;
280        for (Problem problem : getProblems()) {
281            if (problem.getStatus() == Problem.Status.WARNING) ++count;
282        }
283        return count;
284    }
285
286    @Override
287    public int infoCount() {
288        int count = 0;
289        for (Problem problem : getProblems()) {
290            if (problem.getStatus() == Problem.Status.INFO) ++count;
291        }
292        return count;
293    }
294
295    @Override
296    public int size() {
297        return getProblems().size();
298    }
299
300    @Override
301    public Iterator<Problem> iterator() {
302        return getProblems().iterator();
303    }
304
305    protected abstract void addProblem( Problem problem );
306
307    protected abstract List<Problem> getProblems();
308
309    @Override
310    public void writeTo( Logger logger ) {
311        if (hasProblems()) {
312            for (Problem problem : this) {
313                Level level = logLevelFor(problem.getStatus());
314                logger.log(level, problem.getMessage(), problem.getParameters());
315            }
316        }
317    }
318
319    @Override
320    public void writeTo( Logger logger,
321                         Status firstStatus,
322                         Status... additionalStatuses ) {
323        EnumSet<Status> stats = EnumSet.of(firstStatus, additionalStatuses);
324        if (hasProblems()) {
325            for (Problem problem : this) {
326                Status status = problem.getStatus();
327                if (!stats.contains(status)) continue;
328                Level level = logLevelFor(status);
329                logger.log(level, problem.getMessage(), problem.getParameters());
330            }
331        }
332    }
333
334    protected final Level logLevelFor( Status status ) {
335        switch (status) {
336            case ERROR:
337                return Level.ERROR;
338            case WARNING:
339                return Level.WARNING;
340            case INFO:
341                return Level.INFO;
342        }
343        assert false : "Should not happen";
344        return Level.INFO;
345    }
346
347    @Override
348    public void apply( Consumer<Problem> consumer ) {
349        if (consumer != null) {
350            for (Problem problem : getProblems()) {
351                if (problem != null) consumer.accept(problem);
352            }
353        }
354    }
355
356    @Override
357    public void apply( Status status,
358                       Consumer<Problem> consumer ) {
359        if (status != null && consumer != null) {
360            for (Problem problem : getProblems()) {
361                if (problem != null && problem.getStatus() == status) consumer.accept(problem);
362            }
363        }
364    }
365
366    @Override
367    public void apply( EnumSet<Status> statuses,
368                       Consumer<Problem> consumer ) {
369        if (statuses != null && consumer != null) {
370            for (Problem problem : getProblems()) {
371                if (problem != null && statuses.contains(problem.getStatus())) consumer.accept(problem);
372            }
373        }
374    }
375
376    @Override
377    public String toString() {
378        final StringBuilder sb = new StringBuilder();
379        final Consumer<Problem> consumer = new Consumer<Problem>() {
380            private boolean first = true;
381
382            @Override
383            public void accept( Problem problem ) {
384                if (first) first = false;
385                else sb.append("\n");
386                sb.append(problem);
387            }
388        };
389        // Do these in this order, not all at once ...
390        apply(Status.ERROR, consumer);
391        apply(Status.WARNING, consumer);
392        apply(Status.INFO, consumer);
393        return sb.toString();
394    }
395}