001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2022, 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.model;
015
016import java.io.Serializable;
017import java.util.ArrayList;
018import java.util.List;
019import java.util.Objects;
020
021/**
022 * Abstract representation of configuration elements
023 * 
024 * @author Ceki Gülcü
025 * @since 1.3.0
026 */
027public class Model implements Serializable {
028
029    private static final long serialVersionUID = -797372668713068159L;
030
031    // this state should not be here but should be treated via listeners
032    // between processors and ModelHandlers
033    boolean handled = false;
034    boolean skipped = false;
035
036    String tag;
037    String bodyText;
038    int lineNumber;
039
040    List<Model> subModels = new ArrayList<>();
041
042    static public Model duplicate(Model that) {
043        Model copy = that.makeNewInstance();
044        copy.mirror(that);
045        for(Model m: that.subModels) {
046            Model duplicate = duplicate(m);
047            copy.subModels.add(duplicate);
048        }
049        return copy;
050    }
051    
052    protected Model makeNewInstance() {
053        return new Model();
054    }
055    
056    protected void mirror(Model that) {
057        this.tag = that.tag;
058        this.bodyText = that.bodyText;
059        this.lineNumber = that.lineNumber;
060    }
061    
062    
063    public void markAsSkipped() {
064        skipped = true;
065    }
066
067    /**
068     * The model can re-used at reconfiguration time.
069     * 
070     * @since 1.3.0-alpha14
071     */
072    void resetForReuse() {
073       this.handled = false;
074       this.skipped = false;
075       for(Model sub: subModels) {
076           sub.resetForReuse();
077       }
078    }
079    
080    public boolean isSkipped() {
081        return skipped;
082    }
083
084    public boolean isUnhandled() {
085        return !handled;
086    }
087
088    public boolean isHandled() {
089        return handled;
090    }
091
092    public void markAsHandled() {
093        handled = true;
094    }
095
096
097    public String getTag() {
098        return tag;
099    }
100
101    public void setTag(String tag) {
102        this.tag = tag;
103    }
104
105    public int getLineNumber() {
106        return lineNumber;
107    }
108
109    public void setLineNumber(int lineNumber) {
110        this.lineNumber = lineNumber;
111    }
112
113    public List<Model> getSubModels() {
114        return subModels;
115    }
116
117    public void addSubModel(Model m) {
118        subModels.add(m);
119    }
120
121    public String getBodyText() {
122        return bodyText;
123    }
124
125    public void addText(String bodytext) {
126        if (bodyText == null)
127            this.bodyText = bodytext;
128        else
129            this.bodyText += bodytext;
130    }
131
132    public String idString() {
133        return "<" + tag + "> at line " + lineNumber;
134    }
135
136
137    @Override
138    public int hashCode() {
139        return Objects.hash(bodyText, lineNumber, subModels, tag);
140    }
141
142    @Override
143    public boolean equals(Object obj) {
144        if (this == obj)
145            return true;
146        if (obj == null)
147            return false;
148        if (getClass() != obj.getClass())
149            return false;
150        Model other = (Model) obj;
151        return Objects.equals(bodyText, other.bodyText) && lineNumber == other.lineNumber
152                && Objects.equals(subModels, other.subModels) && Objects.equals(tag, other.tag);
153    }
154
155    
156    @Override
157    public String toString() {
158        return this.getClass().getSimpleName() + " [tag=" + tag + ", bodyText=" + bodyText + ", id="+hashCode()+"]";
159    }
160
161}