001/**
002 * Copyright (c) 2004-2011 QOS.ch
003 * All rights reserved.
004 *
005 * Permission is hereby granted, free  of charge, to any person obtaining
006 * a  copy  of this  software  and  associated  documentation files  (the
007 * "Software"), to  deal in  the Software without  restriction, including
008 * without limitation  the rights to  use, copy, modify,  merge, publish,
009 * distribute,  sublicense, and/or sell  copies of  the Software,  and to
010 * permit persons to whom the Software  is furnished to do so, subject to
011 * the following conditions:
012 *
013 * The  above  copyright  notice  and  this permission  notice  shall  be
014 * included in all copies or substantial portions of the Software.
015 *
016 * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
017 * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
018 * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
021 * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023 *
024 */
025package org.slf4j.helpers;
026
027import java.util.Iterator;
028import java.util.List;
029import java.util.concurrent.CopyOnWriteArrayList;
030
031import org.slf4j.Marker;
032
033/**
034 * A simple implementation of the {@link Marker} interface.
035 * 
036 * @author Ceki Gülcü
037 * @author Joern Huxhorn
038 */
039public class BasicMarker implements Marker {
040
041    private static final long serialVersionUID = -2849567615646933777L;
042    private final String name;
043    private final List<Marker> referenceList = new CopyOnWriteArrayList<>();
044
045    BasicMarker(String name) {
046        if (name == null) {
047            throw new IllegalArgumentException("A marker name cannot be null");
048        }
049        this.name = name;
050    }
051
052    public String getName() {
053        return name;
054    }
055
056    public void add(Marker reference) {
057        if (reference == null) {
058            throw new IllegalArgumentException("A null value cannot be added to a Marker as reference.");
059        }
060
061        // no point in adding the reference multiple times
062        if (this.contains(reference)) {
063            return;
064
065        } else if (reference.contains(this)) { // avoid recursion
066            // a potential reference should not hold its future "parent" as a reference
067            return;
068        } else {
069            referenceList.add(reference);
070        }
071    }
072
073    public boolean hasReferences() {
074        return (referenceList.size() > 0);
075    }
076
077    @Deprecated
078    public boolean hasChildren() {
079        return hasReferences();
080    }
081
082    public Iterator<Marker> iterator() {
083        return referenceList.iterator();
084    }
085
086    public boolean remove(Marker referenceToRemove) {
087        return referenceList.remove(referenceToRemove);
088    }
089
090    public boolean contains(Marker other) {
091        if (other == null) {
092            throw new IllegalArgumentException("Other cannot be null");
093        }
094
095        if (this.equals(other)) {
096            return true;
097        }
098
099        if (hasReferences()) {
100            for (Marker ref : referenceList) {
101                if (ref.contains(other)) {
102                    return true;
103                }
104            }
105        }
106        return false;
107    }
108
109    /**
110     * This method is mainly used with Expression Evaluators.
111     */
112    public boolean contains(String name) {
113        if (name == null) {
114            throw new IllegalArgumentException("Other cannot be null");
115        }
116
117        if (this.name.equals(name)) {
118            return true;
119        }
120
121        if (hasReferences()) {
122            for (Marker ref : referenceList) {
123                if (ref.contains(name)) {
124                    return true;
125                }
126            }
127        }
128        return false;
129    }
130
131    private static final String OPEN = "[ ";
132    private static final String CLOSE = " ]";
133    private static final String SEP = ", ";
134
135    public boolean equals(Object obj) {
136        if (this == obj)
137            return true;
138        if (obj == null)
139            return false;
140        if (!(obj instanceof Marker))
141            return false;
142
143        final Marker other = (Marker) obj;
144        return name.equals(other.getName());
145    }
146
147    public int hashCode() {
148        return name.hashCode();
149    }
150
151    public String toString() {
152        if (!this.hasReferences()) {
153            return this.getName();
154        }
155        Iterator<Marker> it = this.iterator();
156        Marker reference;
157        StringBuilder sb = new StringBuilder(this.getName());
158        sb.append(' ').append(OPEN);
159        while (it.hasNext()) {
160            reference = it.next();
161            sb.append(reference.getName());
162            if (it.hasNext()) {
163                sb.append(SEP);
164            }
165        }
166        sb.append(CLOSE);
167
168        return sb.toString();
169    }
170}