001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.status;
015
016import java.util.ArrayList;
017import java.util.Iterator;
018import java.util.List;
019
020abstract public class StatusBase implements Status {
021
022    static private final List<Status> EMPTY_LIST = new ArrayList<Status>(0);
023
024    int level;
025    final String message;
026    final Object origin;
027    List<Status> childrenList;
028    Throwable throwable;
029    long date;
030
031    StatusBase(int level, String msg, Object origin) {
032        this(level, msg, origin, null);
033    }
034
035    StatusBase(int level, String msg, Object origin, Throwable t) {
036        this.level = level;
037        this.message = msg;
038        this.origin = origin;
039        this.throwable = t;
040        this.date = System.currentTimeMillis();
041    }
042
043    public synchronized void add(Status child) {
044        if (child == null) {
045            throw new NullPointerException("Null values are not valid Status.");
046        }
047        if (childrenList == null) {
048            childrenList = new ArrayList<Status>();
049        }
050        childrenList.add(child);
051    }
052
053    public synchronized boolean hasChildren() {
054        return ((childrenList != null) && (childrenList.size() > 0));
055    }
056
057    public synchronized Iterator<Status> iterator() {
058        if (childrenList != null) {
059            return childrenList.iterator();
060        } else {
061            return EMPTY_LIST.iterator();
062        }
063    }
064
065    public synchronized boolean remove(Status statusToRemove) {
066        if (childrenList == null) {
067            return false;
068        }
069        // TODO also search in childrens' children
070        return childrenList.remove(statusToRemove);
071    }
072
073    public int getLevel() {
074        return level;
075    }
076
077    // status messages are not supposed to contain cycles.
078    // cyclic status arrangements are like to cause deadlocks
079    // when this method is called from different thread on
080    // different status objects lying on the same cycle
081    public synchronized int getEffectiveLevel() {
082        int result = level;
083        int effLevel;
084
085        Iterator<Status> it = iterator();
086        Status s;
087        while (it.hasNext()) {
088            s = (Status) it.next();
089            effLevel = s.getEffectiveLevel();
090            if (effLevel > result) {
091                result = effLevel;
092            }
093        }
094        return result;
095    }
096
097    public String getMessage() {
098        return message;
099    }
100
101    public Object getOrigin() {
102        return origin;
103    }
104
105    public Throwable getThrowable() {
106        return throwable;
107    }
108
109    public Long getDate() {
110        return date;
111    }
112
113    @Override
114    public String toString() {
115        StringBuilder buf = new StringBuilder();
116        switch (getEffectiveLevel()) {
117        case INFO:
118            buf.append("INFO");
119            break;
120        case WARN:
121            buf.append("WARN");
122            break;
123        case ERROR:
124            buf.append("ERROR");
125            break;
126        }
127        if (origin != null) {
128            buf.append(" in ");
129            buf.append(origin);
130            buf.append(" -");
131        }
132
133        buf.append(" ");
134        buf.append(message);
135
136        if (throwable != null) {
137            buf.append(" ");
138            buf.append(throwable);
139        }
140
141        return buf.toString();
142    }
143
144    @Override
145    public int hashCode() {
146        final int prime = 31;
147        int result = 1;
148        result = prime * result + level;
149        result = prime * result + ((message == null) ? 0 : message.hashCode());
150        return result;
151    }
152
153    @Override
154    public boolean equals(Object obj) {
155        if (this == obj)
156            return true;
157        if (obj == null)
158            return false;
159        if (getClass() != obj.getClass())
160            return false;
161        final StatusBase other = (StatusBase) obj;
162        if (level != other.level)
163            return false;
164        if (message == null) {
165            if (other.message != null)
166                return false;
167        } else if (!message.equals(other.message))
168            return false;
169        return true;
170    }
171
172}