1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v2.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.joran.action;
15  
16  import org.xml.sax.Attributes;
17  
18  import ch.qos.logback.core.joran.JoranConstants;
19  import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
20  import ch.qos.logback.core.spi.ContextAware;
21  import ch.qos.logback.core.spi.ContextAwareBase;
22  import ch.qos.logback.core.util.OptionHelper;
23  
24  public class PreconditionValidator extends ContextAwareBase {
25  
26      boolean valid = true;
27      SaxEventInterpretationContext seic;
28      Attributes attributes;
29      String tag;
30  
31      public PreconditionValidator(ContextAware origin, SaxEventInterpretationContext seic, String name,
32              Attributes attributes) {
33          super(origin);
34          this.setContext(origin.getContext());
35          this.seic = seic;
36          this.tag = name;
37          this.attributes = attributes;
38      }
39  
40      public PreconditionValidator validateZeroAttributes() {
41          if(attributes == null) 
42              return this;
43          
44          if(attributes.getLength() != 0) {
45              addError("Element [" + tag + "] should have no attributes, near line "
46                      + Action.getLineNumber(seic));
47              this.valid = false;
48          }
49          return this;
50      }
51  
52      
53      public PreconditionValidator validateClassAttribute() {
54          return validateGivenAttribute(Action.CLASS_ATTRIBUTE);
55      }
56  
57      public PreconditionValidator validateNameAttribute() {
58          return validateGivenAttribute(Action.NAME_ATTRIBUTE);
59      }
60  
61      public PreconditionValidator validateValueAttribute() {
62          return validateGivenAttribute(JoranConstants.VALUE_ATTR);
63      }
64  
65      public PreconditionValidator validateRefAttribute() {
66          return validateGivenAttribute(JoranConstants.REF_ATTRIBUTE);
67      }
68  
69      public PreconditionValidator validateOneAndOnlyOneAttributeProvided(String... names) {
70          int validCount = 0;
71          for(String name : names) {
72              boolean invalid = isInvalidAttribute(name);
73              if(!invalid) {
74                  validCount++;
75              }
76          }
77          if(validCount == 1) {
78              this.valid = true;
79          } else {
80              this.valid = false;
81              addError("Element [" + tag + "] should have at least one of [" + names + "] as an attribute, near line "
82                      + Action.getLineNumber(seic));
83          }
84          return this;
85      }
86  
87      public boolean isInvalidAttribute(String attributeName) {
88          String attributeValue = attributes.getValue(attributeName);
89          return OptionHelper.isNullOrEmptyOrAllSpaces(attributeValue);
90      }
91  
92      public PreconditionValidator validateGivenAttribute(String attributeName) {
93          boolean invalid = isInvalidAttribute(attributeName);
94          if (invalid) {
95              addMissingAttributeError(attributeName);
96              this.valid = false;
97          }
98          return this;
99      }
100 
101 
102 
103     /**
104      *
105      * @deprecated replaced by {@link #validateGivenAttribute(String)}
106      */
107     @Deprecated
108     public PreconditionValidator generic(String attributeName) {
109         return validateGivenAttribute(attributeName);
110     }
111 
112     public void addMissingAttributeError(String attributeName) {
113         addError("Missing attribute [" + attributeName + "]. " + getLocationSuffix());
114     }
115 
116     public String getLocationSuffix() {
117         return "See element [" + tag + "] near line " + Action.getLineNumber(seic);
118     }
119 
120 //    public void addWarning(String msg) {
121 //        super.addWarn(msg + getLocationSuffix());
122 //    }
123 //
124 //    public void addError(String msg) {
125 //        super.addError(msg + getLocationSuffix());
126 //    }
127 
128     public boolean isValid() {
129         return valid;
130     }
131 
132 }