    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&uuml;lc&uuml;
    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}