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    /**
057     * @deprecated Markers are now immutable and no longer support children.
058     */
059    @Override
060    @Deprecated
061    public void add(Marker reference) {
062        if (reference == null) {
063            throw new IllegalArgumentException("A null value cannot be added to a Marker as reference.");
064        }
065
066        // no point in adding the reference multiple times
067        if (this.contains(reference)) {
068            return;
069
070        } else if (reference.contains(this)) { // avoid recursion
071            // a potential reference should not hold its future "parent" as a reference
072            return;
073        } else {
074            referenceList.add(reference);
075        }
076    }
077
078    /**
079     * @deprecated Markers are now immutable and no longer support children.
080     */
081    @Override
082    @Deprecated
083    public boolean hasReferences() {
084        return (referenceList.size() > 0);
085    }
086
087    /**
088     * @deprecated Markers are now immutable and no longer support children.
089     */
090    @Override
091    @Deprecated
092    public boolean hasChildren() {
093        return hasReferences();
094    }
095
096    /**
097     * @deprecated Markers are now immutable and no longer support children.
098     */
099    @Override
100    @Deprecated
101    public Iterator<Marker> iterator() {
102        return referenceList.iterator();
103    }
104
105
106    /**
107     * @deprecated Markers are now immutable and no longer support children.
108     */
109    @Override
110    @Deprecated
111    public boolean remove(Marker referenceToRemove) {
112        return referenceList.remove(referenceToRemove);
113    }
114
115    /**
116     * @deprecated Markers are now immutable and no longer support children.
117     */
118    @Override
119    @Deprecated
120    public boolean contains(Marker other) {
121        if (other == null) {
122            throw new IllegalArgumentException("Other cannot be null");
123        }
124
125        if (this.equals(other)) {
126            return true;
127        }
128
129        if (hasReferences()) {
130            for (Marker ref : referenceList) {
131                if (ref.contains(other)) {
132                    return true;
133                }
134            }
135        }
136        return false;
137    }
138
139    /**
140     * This method is mainly used with Expression Evaluators.
141     */
142    public boolean contains(String name) {
143        if (name == null) {
144            throw new IllegalArgumentException("Other cannot be null");
145        }
146
147        if (this.name.equals(name)) {
148            return true;
149        }
150
151        if (hasReferences()) {
152            for (Marker ref : referenceList) {
153                if (ref.contains(name)) {
154                    return true;
155                }
156            }
157        }
158        return false;
159    }
160
161    private static final String OPEN = "[ ";
162    private static final String CLOSE = " ]";
163    private static final String SEP = ", ";
164
165    public boolean equals(Object obj) {
166        if (this == obj)
167            return true;
168        if (obj == null)
169            return false;
170        if (!(obj instanceof Marker))
171            return false;
172
173        final Marker other = (Marker) obj;
174        return name.equals(other.getName());
175    }
176
177    public int hashCode() {
178        return name.hashCode();
179    }
180
181    public String toString() {
182        if (!this.hasReferences()) {
183            return this.getName();
184        }
185        Iterator<Marker> it = this.iterator();
186        Marker reference;
187        StringBuilder sb = new StringBuilder(this.getName());
188        sb.append(' ').append(OPEN);
189        while (it.hasNext()) {
190            reference = it.next();
191            sb.append(reference.getName());
192            if (it.hasNext()) {
193                sb.append(SEP);
194            }
195        }
196        sb.append(CLOSE);
197
198        return sb.toString();
199    }
200}