17ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu/**
27ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * Copyright (c) 2004-2011 QOS.ch
388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * All rights reserved.
47ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu *
588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * Permission is hereby granted, free  of charge, to any person obtaining
688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * a  copy  of this  software  and  associated  documentation files  (the
788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * "Software"), to  deal in  the Software without  restriction, including
888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * without limitation  the rights to  use, copy, modify,  merge, publish,
988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * distribute,  sublicense, and/or sell  copies of  the Software,  and to
1088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * permit persons to whom the Software  is furnished to do so, subject to
1188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * the following conditions:
127ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu *
1388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * The  above  copyright  notice  and  this permission  notice  shall  be
1488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * included in all copies or substantial portions of the Software.
157ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu *
1688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
1788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
1888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
1988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
2088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
2288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
237ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu *
2488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu */
2588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcupackage org.slf4j.helpers;
2688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
2788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport java.util.Collections;
2888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport java.util.Iterator;
2988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport java.util.List;
3088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport java.util.Vector;
3188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
3288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport org.slf4j.Marker;
3388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
3488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu/**
3588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * A simple implementation of the {@link Marker} interface.
3688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu *
3788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * @author Ceki Gülcü
3888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * @author Joern Huxhorn
3988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu */
4088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcupublic class BasicMarker implements Marker {
4188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
4231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    private static final long serialVersionUID = 1803952589649545191L;
4388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
4431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    private final String name;
4531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    private List<Marker> referenceList;
4688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
4731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    BasicMarker(String name) {
4831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (name == null) {
4931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            throw new IllegalArgumentException("A marker name cannot be null");
5031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
5131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        this.name = name;
5288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
5388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
5431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public String getName() {
5531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return name;
5688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
5788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
5831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public synchronized void add(Marker reference) {
5931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (reference == null) {
6031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            throw new IllegalArgumentException("A null value cannot be added to a Marker as reference.");
6131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
6288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
6331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        // no point in adding the reference multiple times
6431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (this.contains(reference)) {
6531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return;
6631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu
6731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        } else if (reference.contains(this)) { // avoid recursion
6831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            // a potential reference should not its future "parent" as a reference
6931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return;
7031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        } else {
7131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            // let's add the reference
7231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            if (referenceList == null) {
7331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                referenceList = new Vector<Marker>();
7431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            }
7531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            referenceList.add(reference);
7631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
7788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
7888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
7988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
8031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public synchronized boolean hasReferences() {
8131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return ((referenceList != null) && (referenceList.size() > 0));
8288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
8388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
8431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public boolean hasChildren() {
8531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return hasReferences();
8688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
8788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
8831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public synchronized Iterator<Marker> iterator() {
8931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (referenceList != null) {
9031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return referenceList.iterator();
9131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        } else {
9231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            List<Marker> emptyList = Collections.emptyList();
9331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return emptyList.iterator();
9431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
9588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
9688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
9731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public synchronized boolean remove(Marker referenceToRemove) {
9831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (referenceList == null) {
9931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return false;
10088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu        }
10188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
10231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        int size = referenceList.size();
10331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        for (int i = 0; i < size; i++) {
10431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            Marker m = (Marker) referenceList.get(i);
10531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            if (referenceToRemove.equals(m)) {
10631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                referenceList.remove(i);
10731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                return true;
10831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            }
10931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
11031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return false;
11188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
11288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
11331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public boolean contains(Marker other) {
11431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (other == null) {
11531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            throw new IllegalArgumentException("Other cannot be null");
11631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
11731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu
11831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (this.equals(other)) {
11931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return true;
12088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu        }
12131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu
12231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (hasReferences()) {
12331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            for (int i = 0; i < referenceList.size(); i++) {
12431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                Marker ref = (Marker) referenceList.get(i);
12531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                if (ref.contains(other)) {
12631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                    return true;
12731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                }
12831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            }
12931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
13031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return false;
13188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
13288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
13331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    /**
13431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu     * This method is mainly used with Expression Evaluators.
13531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu     */
13631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public boolean contains(String name) {
13731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (name == null) {
13831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            throw new IllegalArgumentException("Other cannot be null");
13931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
14088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
14131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (this.name.equals(name)) {
14231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return true;
14331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
14488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
14531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (hasReferences()) {
14631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            for (int i = 0; i < referenceList.size(); i++) {
14731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                Marker ref = (Marker) referenceList.get(i);
14831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                if (ref.contains(name)) {
14931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                    return true;
15031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                }
15131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            }
15231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
15331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return false;
15431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    }
15588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
15631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    private static String OPEN = "[ ";
15731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    private static String CLOSE = " ]";
15831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    private static String SEP = ", ";
15988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
16031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public boolean equals(Object obj) {
16131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (this == obj)
16231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return true;
16331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (obj == null)
16431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return false;
16531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (!(obj instanceof Marker))
16631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return false;
16788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
16831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        final Marker other = (Marker) obj;
16931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return name.equals(other.getName());
17088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
17131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu
17231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public int hashCode() {
17331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return name.hashCode();
17488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu    }
17588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu
17631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    public String toString() {
17731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        if (!this.hasReferences()) {
17831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            return this.getName();
17931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
18031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        Iterator<Marker> it = this.iterator();
18131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        Marker reference;
18231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        StringBuilder sb = new StringBuilder(this.getName());
18331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        sb.append(' ').append(OPEN);
18431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        while (it.hasNext()) {
18531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            reference = (Marker) it.next();
18631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            sb.append(reference.getName());
18731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            if (it.hasNext()) {
18831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu                sb.append(SEP);
18931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu            }
19031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        }
19131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        sb.append(CLOSE);
19231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu
19331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu        return sb.toString();
19431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu    }
19588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu}
196