/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.model.labels;
import hudson.model.Label;
import hudson.util.VariableResolver;
/**
* Boolean expression of labels.
*
* @author Kohsuke Kawaguchi
* @since 1.372
*/
public abstract class LabelExpression extends Label {
protected LabelExpression(String name) {
super(name);
}
@Override
public String getExpression() {
return getDisplayName();
}
public static class Not extends LabelExpression {
private final Label base;
public Not(Label base) {
super('!'+paren(LabelOperatorPrecedence.NOT,base));
this.base = base;
}
@Override
public boolean matches(VariableResolver<Boolean> resolver) {
return !base.matches(resolver);
}
@Override
public LabelOperatorPrecedence precedence() {
return LabelOperatorPrecedence.NOT;
}
}
/**
* No-op but useful for preserving the parenthesis in the user input.
*/
public static class Paren extends LabelExpression {
private final Label base;
public Paren(Label base) {
super('('+base.getExpression()+')');
this.base = base;
}
@Override
public boolean matches(VariableResolver<Boolean> resolver) {
return base.matches(resolver);
}
@Override
public LabelOperatorPrecedence precedence() {
return LabelOperatorPrecedence.ATOM;
}
}
/**
* Puts the label name into a parenthesis if the given operator will have a higher precedence.
*/
static String paren(LabelOperatorPrecedence op, Label l) {
if (op.compareTo(l.precedence())<0)
return '('+l.getExpression()+')';
return l.getExpression();
}
public static abstract class Binary extends LabelExpression {
private final Label lhs,rhs;
public Binary(Label lhs, Label rhs, LabelOperatorPrecedence op) {
super(combine(lhs, rhs, op));
this.lhs = lhs;
this.rhs = rhs;
}
private static String combine(Label lhs, Label rhs, LabelOperatorPrecedence op) {
return paren(op,lhs)+op.str+paren(op,rhs);
}
/**
* Note that we evaluate both branches of the expression all the time.
* That is, it behaves like "a|b" not "a||b"
*/
@Override
public boolean matches(VariableResolver<Boolean> resolver) {
return op(lhs.matches(resolver),rhs.matches(resolver));
}
protected abstract boolean op(boolean a, boolean b);
}
public static final class And extends Binary {
public And(Label lhs, Label rhs) {
super(lhs, rhs, LabelOperatorPrecedence.AND);
}
@Override
protected boolean op(boolean a, boolean b) {
return a && b;
}
@Override
public LabelOperatorPrecedence precedence() {
return LabelOperatorPrecedence.AND;
}
}
public static final class Or extends Binary {
public Or(Label lhs, Label rhs) {
super(lhs, rhs, LabelOperatorPrecedence.OR);
}
@Override
protected boolean op(boolean a, boolean b) {
return a || b;
}
@Override
public LabelOperatorPrecedence precedence() {
return LabelOperatorPrecedence.OR;
}
}
public static final class Iff extends Binary {
public Iff(Label lhs, Label rhs) {
super(lhs, rhs, LabelOperatorPrecedence.IFF);
}
@Override
protected boolean op(boolean a, boolean b) {
return !(a ^ b);
}
@Override
public LabelOperatorPrecedence precedence() {
return LabelOperatorPrecedence.IFF;
}
}
public static final class Implies extends Binary {
public Implies(Label lhs, Label rhs) {
super(lhs, rhs, LabelOperatorPrecedence.IMPLIES);
}
@Override
protected boolean op(boolean a, boolean b) {
return !a || b;
}
@Override
public LabelOperatorPrecedence precedence() {
return LabelOperatorPrecedence.IMPLIES;
}
}
}