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    public void deepMarkAsSkipped() {
067        markAsSkipped();
068        for(Model m: this.getSubModels()) {
069            m.deepMarkAsSkipped();
070        }
071    }
072    /**
073     * The model can re-used at reconfiguration time.
074     * 
075     * @since 1.3.0-alpha14
076     */
077    void resetForReuse() {
078       this.handled = false;
079       this.skipped = false;
080       for(Model sub: subModels) {
081           sub.resetForReuse();
082       }
083    }
084    
085    public boolean isSkipped() {
086        return skipped;
087    }
088
089    public boolean isUnhandled() {
090        return !handled;
091    }
092
093    public boolean isHandled() {
094        return handled;
095    }
096
097    public void markAsHandled() {
098        handled = true;
099    }
100
101
102
103
104    public String getTag() {
105        return tag;
106    }
107
108    public void setTag(String tag) {
109        this.tag = tag;
110    }
111
112    public int getLineNumber() {
113        return lineNumber;
114    }
115
116    public void setLineNumber(int lineNumber) {
117        this.lineNumber = lineNumber;
118    }
119
120    public List<Model> getSubModels() {
121        return subModels;
122    }
123
124    public void addSubModel(Model m) {
125        subModels.add(m);
126    }
127
128    public String getBodyText() {
129        return bodyText;
130    }
131
132    public void addText(String bodytext) {
133        if (bodyText == null)
134            this.bodyText = bodytext;
135        else
136            this.bodyText += bodytext;
137    }
138
139    public String idString() {
140        return "<" + tag + "> at line " + lineNumber;
141    }
142
143
144    @Override
145    public int hashCode() {
146        return Objects.hash(bodyText, lineNumber, subModels, tag);
147    }
148
149    @Override
150    public boolean equals(Object obj) {
151        if (this == obj)
152            return true;
153        if (obj == null)
154            return false;
155        if (getClass() != obj.getClass())
156            return false;
157        Model other = (Model) obj;
158        return Objects.equals(bodyText, other.bodyText) && lineNumber == other.lineNumber
159                && Objects.equals(subModels, other.subModels) && Objects.equals(tag, other.tag);
160    }
161
162    
163    @Override
164    public String toString() {
165        return this.getClass().getSimpleName() + " [tag=" + tag + ", bodyText=" + bodyText + ", id="+hashCode()+"]";
166    }
167
168}