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.ArrayList;
019import java.util.Collections;
020import java.util.LinkedList;
021import java.util.List;
022import java.util.concurrent.locks.ReadWriteLock;
023import java.util.concurrent.locks.ReentrantReadWriteLock;
024import org.modeshape.common.annotation.ThreadSafe;
025
026/**
027 * A thread-safe {@link Problems} collection. The problems will be {@link #iterator() returned} in the order in which they were
028 * encountered.
029 */
030@ThreadSafe
031public class ThreadSafeProblems extends AbstractProblems {
032    private static final long serialVersionUID = 1L;
033
034    private final ReadWriteLock lock = new ReentrantReadWriteLock();
035    private final List<Problem> problems = new LinkedList<Problem>();
036
037    @Override
038    public boolean hasErrors() {
039        try {
040            lock.readLock().lock();
041            return super.hasErrors();
042        } finally {
043            lock.readLock().unlock();
044        }
045    }
046
047    @Override
048    public boolean hasProblems() {
049        try {
050            lock.readLock().lock();
051            return super.hasProblems();
052        } finally {
053            lock.readLock().unlock();
054        }
055    }
056
057    @Override
058    public boolean hasInfo() {
059        try {
060            lock.readLock().lock();
061            return super.hasInfo();
062        } finally {
063            lock.readLock().unlock();
064        }
065    }
066
067    @Override
068    public boolean hasWarnings() {
069        try {
070            lock.readLock().lock();
071            return super.hasWarnings();
072        } finally {
073            lock.readLock().unlock();
074        }
075    }
076
077    @Override
078    public boolean isEmpty() {
079        try {
080            lock.readLock().lock();
081            return super.isEmpty();
082        } finally {
083            lock.readLock().unlock();
084        }
085    }
086
087    @Override
088    public int size() {
089        try {
090            lock.readLock().lock();
091            return super.size();
092        } finally {
093            lock.readLock().unlock();
094        }
095    }
096
097    @Override
098    protected void addProblem( Problem problem ) {
099        try {
100            lock.writeLock().lock();
101            problems.add(problem);
102        } finally {
103            lock.writeLock().unlock();
104        }
105    }
106
107    @Override
108    public void addAll( Iterable<Problem> problems ) {
109        if (problems == this) return;
110        try {
111            lock.writeLock().lock();
112            if (problems != null) {
113                for (Problem problem : problems) {
114                    this.problems.add(problem);
115                }
116            }
117        } finally {
118            lock.writeLock().unlock();
119        }
120    }
121
122    @Override
123    protected List<Problem> getProblems() {
124        // Return an unmodifiable copy ...
125        try {
126            lock.readLock().lock();
127            return Collections.unmodifiableList(new ArrayList<Problem>(this.problems));
128        } finally {
129            lock.readLock().unlock();
130        }
131    }
132}