001/*
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2026, 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 v2.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.joran.action;
015
016import org.xml.sax.Attributes;
017
018import ch.qos.logback.core.joran.JoranConstants;
019import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
020import ch.qos.logback.core.spi.ContextAware;
021import ch.qos.logback.core.spi.ContextAwareBase;
022import ch.qos.logback.core.util.OptionHelper;
023
024public class PreconditionValidator extends ContextAwareBase {
025
026    boolean valid = true;
027    SaxEventInterpretationContext seic;
028    Attributes attributes;
029    String tag;
030
031    public PreconditionValidator(ContextAware origin, SaxEventInterpretationContext seic, String name,
032            Attributes attributes) {
033        super(origin);
034        this.setContext(origin.getContext());
035        this.seic = seic;
036        this.tag = name;
037        this.attributes = attributes;
038    }
039
040    public PreconditionValidator validateZeroAttributes() {
041        if(attributes == null) 
042            return this;
043        
044        if(attributes.getLength() != 0) {
045            addError("Element [" + tag + "] should have no attributes, near line "
046                    + Action.getLineNumber(seic));
047            this.valid = false;
048        }
049        return this;
050    }
051
052    
053    public PreconditionValidator validateClassAttribute() {
054        return validateGivenAttribute(Action.CLASS_ATTRIBUTE);
055    }
056
057    public PreconditionValidator validateNameAttribute() {
058        return validateGivenAttribute(Action.NAME_ATTRIBUTE);
059    }
060
061    public PreconditionValidator validateValueAttribute() {
062        return validateGivenAttribute(JoranConstants.VALUE_ATTR);
063    }
064
065    public PreconditionValidator validateRefAttribute() {
066        return validateGivenAttribute(JoranConstants.REF_ATTRIBUTE);
067    }
068
069    public PreconditionValidator validateOneAndOnlyOneAttributeProvided(String... names) {
070        int validCount = 0;
071        for(String name : names) {
072            boolean invalid = isInvalidAttribute(name);
073            if(!invalid) {
074                validCount++;
075            }
076        }
077        if(validCount == 1) {
078            this.valid = true;
079        } else {
080            this.valid = false;
081            addError("Element [" + tag + "] should have at least one of [" + names + "] as an attribute, near line "
082                    + Action.getLineNumber(seic));
083        }
084        return this;
085    }
086
087    public boolean isInvalidAttribute(String attributeName) {
088        String attributeValue = attributes.getValue(attributeName);
089        return OptionHelper.isNullOrEmptyOrAllSpaces(attributeValue);
090    }
091
092    public PreconditionValidator validateGivenAttribute(String attributeName) {
093        boolean invalid = isInvalidAttribute(attributeName);
094        if (invalid) {
095            addMissingAttributeError(attributeName);
096            this.valid = false;
097        }
098        return this;
099    }
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}