1   /* 
2    * Copyright (c) 2004-2008 QOS.ch
3    * All rights reserved.
4    * 
5    * Permission is hereby granted, free  of charge, to any person obtaining
6    * a  copy  of this  software  and  associated  documentation files  (the
7    * "Software"), to  deal in  the Software without  restriction, including
8    * without limitation  the rights to  use, copy, modify,  merge, publish,
9    * distribute,  sublicense, and/or sell  copies of  the Software,  and to
10   * permit persons to whom the Software  is furnished to do so, subject to
11   * the following conditions:
12   * 
13   * The  above  copyright  notice  and  this permission  notice  shall  be
14   * included in all copies or substantial portions of the Software.
15   * 
16   * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
17   * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
18   * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
19   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21   * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
22   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23   */
24  
25  package org.slf4j.helpers;
26  
27  import java.util.Collections;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Vector;
31  
32  import org.slf4j.Marker;
33  
34  /**
35   * An almost trivial implementation of the {@link Marker} interface.
36   * 
37   * <p>
38   * <code>BasicMarker</code> lets users specify marker information. However, it
39   * does not offer any useful operations on that information.
40   * 
41   * <p>
42   * Simple logging systems which ignore marker data, just return instances of
43   * this class in order to conform to the SLF4J API.
44   * 
45   * @author Ceki G&uuml;lc&uuml;
46   * @author Joern Huxhorn
47   */
48  public class BasicMarker implements Marker {
49  
50    private static final long serialVersionUID = 1803952589649545191L;
51  
52    private final String name;
53    private List children;
54  
55    BasicMarker(String name) {
56      if (name == null) {
57        throw new IllegalArgumentException("A merker name cannot be null");
58      }
59      this.name = name;
60    }
61  
62    public String getName() {
63      return name;
64    }
65  
66    public synchronized void add(Marker markerToAddAsChild) {
67      if (markerToAddAsChild == null) {
68        throw new IllegalArgumentException(
69            "A null value cannot be added to a Marker as child.");
70      }
71  
72      // no point in adding the child multiple times
73      if (this.contains(markerToAddAsChild)) {
74        return;
75  
76      } else if (markerToAddAsChild.contains(this)) { // avoid recursion
77        // a potential child should not its future parent as a child
78        return;
79      } else {
80        // let's add the child
81        if (children == null) {
82          children = new Vector();
83        }
84        children.add(markerToAddAsChild);
85      }
86  
87    }
88  
89    public synchronized boolean hasChildren() {
90      return ((children != null) && (children.size() > 0));
91    }
92  
93    public synchronized Iterator iterator() {
94      if (children != null) {
95        return children.iterator();
96      } else {
97        return Collections.EMPTY_LIST.iterator();
98      }
99    }
100 
101   public synchronized boolean remove(Marker markerToRemove) {
102     if (children == null) {
103       return false;
104     }
105 
106     int size = children.size();
107     for (int i = 0; i < size; i++) {
108       Marker m = (Marker) children.get(i);
109       if (m == markerToRemove) {
110         children.remove(i);
111         return true;
112       }
113     }
114     // could not find markerToRemove
115     return false;
116   }
117 
118   public boolean contains(Marker other) {
119     if (other == null) {
120       throw new IllegalArgumentException("Other cannot be null");
121     }
122 
123     if (this == other) {
124       return true;
125     }
126 
127     if (hasChildren()) {
128       for (int i = 0; i < children.size(); i++) {
129         Marker child = (Marker) children.get(i);
130         if (child.contains(other)) {
131           return true;
132         }
133       }
134     }
135     return false;
136   }
137 
138   /**
139    * This method is mainly used with Expression Evaluators.
140    */
141   public boolean contains(String name) {
142     if (name == null) {
143       throw new IllegalArgumentException("Other cannot be null");
144     }
145 
146     if (this.name.equals(name)) {
147       return true;
148     }
149 
150     if (hasChildren()) {
151       for (int i = 0; i < children.size(); i++) {
152         Marker child = (Marker) children.get(i);
153         if (child.contains(name)) {
154           return true;
155         }
156       }
157     }
158     return false;
159   }
160 
161   private static String OPEN = "[ ";
162   private static String CLOSE = " ]";
163   private static String SEP = ", ";
164 
165 
166   public boolean equals(Object obj) {
167     if (this == obj)
168       return true;
169     if (obj == null)
170       return false;
171     if (!(obj instanceof Marker))
172       return false;
173 
174     final Marker other = (Marker) obj;
175     return name.equals(other.getName());
176   }
177 
178   public int hashCode() {
179     return name.hashCode();
180   }
181 
182   public String toString() {
183     if (!this.hasChildren()) {
184       return this.getName();
185     }
186     Iterator it = this.iterator();
187     Marker child;
188     StringBuffer sb = new StringBuffer(this.getName());
189     sb.append(' ').append(OPEN);
190     while (it.hasNext()) {
191       child = (Marker) it.next();
192       sb.append(child.getName());
193       if (it.hasNext()) {
194         sb.append(SEP);
195       }
196     }
197     sb.append(CLOSE);
198 
199     return sb.toString();
200   }
201 }