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 List<Marker> referenceList = new CopyOnWriteArrayList<Marker>();
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    public boolean hasChildren() {
078        return hasReferences();
079    }
080
081    public Iterator<Marker> iterator() {
082      return referenceList.iterator();
083    }
084
085    public boolean remove(Marker referenceToRemove) {
086        return referenceList.remove(referenceToRemove);
087    }
088
089    public boolean contains(Marker other) {
090        if (other == null) {
091            throw new IllegalArgumentException("Other cannot be null");
092        }
093
094        if (this.equals(other)) {
095            return true;
096        }
097
098        if (hasReferences()) {
099            for (Marker ref : referenceList) {
100                if (ref.contains(other)) {
101                    return true;
102                }
103            }
104        }
105        return false;
106    }
107
108    /**
109     * This method is mainly used with Expression Evaluators.
110     */
111    public boolean contains(String name) {
112        if (name == null) {
113            throw new IllegalArgumentException("Other cannot be null");
114        }
115
116        if (this.name.equals(name)) {
117            return true;
118        }
119
120        if (hasReferences()) {
121            for (Marker ref : referenceList) {
122                if (ref.contains(name)) {
123                    return true;
124                }
125            }
126        }
127        return false;
128    }
129
130    private static String OPEN = "[ ";
131    private static String CLOSE = " ]";
132    private static String SEP = ", ";
133
134    public boolean equals(Object obj) {
135        if (this == obj)
136            return true;
137        if (obj == null)
138            return false;
139        if (!(obj instanceof Marker))
140            return false;
141
142        final Marker other = (Marker) obj;
143        return name.equals(other.getName());
144    }
145
146    public int hashCode() {
147        return name.hashCode();
148    }
149
150    public String toString() {
151        if (!this.hasReferences()) {
152            return this.getName();
153        }
154        Iterator<Marker> it = this.iterator();
155        Marker reference;
156        StringBuilder sb = new StringBuilder(this.getName());
157        sb.append(' ').append(OPEN);
158        while (it.hasNext()) {
159            reference = it.next();
160            sb.append(reference.getName());
161            if (it.hasNext()) {
162                sb.append(SEP);
163            }
164        }
165        sb.append(CLOSE);
166
167        return sb.toString();
168    }
169}