com.hpcloud.mon.common.model.alarm.AlarmExpression.java Source code

Java tutorial

Introduction

Here is the source code for com.hpcloud.mon.common.model.alarm.AlarmExpression.java

Source

/*
 * Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hpcloud.mon.common.model.alarm;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.hpcloud.util.Stack;

/**
 * Alarm expression value object.
 */
public class AlarmExpression {
    private final String expression;
    /** Postfix list of expression elements. */
    private final List<Object> elements;
    private volatile List<AlarmSubExpression> subExpressions;

    /**
     * Creates an AlarmExpression for the {@code expression} string.
     * 
     * @throws IllegalArgumentException if the {@code expression} is invalid
     */
    public AlarmExpression(String expression) {
        this.expression = expression;
        AlarmExpressionParser parser = new AlarmExpressionParser(
                new CommonTokenStream(new AlarmExpressionLexer(new ANTLRInputStream(expression))));
        parser.removeErrorListeners();
        parser.addErrorListener(new AlarmExpressionErrorListener());
        parser.setBuildParseTree(true);
        ParserRuleContext tree = parser.start();
        AlarmSubExpressionListener listener = new AlarmSubExpressionListener(false);
        ParseTreeWalker walker = new ParseTreeWalker();
        walker.walk(listener, tree);
        elements = listener.getElements();
    }

    /**
     * Creates an AlarmExpression for the {@code expression} string.
     * 
     * @throws IllegalArgumentException if the {@code expression} is invalid
     */
    @JsonCreator
    public static AlarmExpression of(String expression) {
        return new AlarmExpression(expression);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        AlarmExpression other = (AlarmExpression) obj;
        if (elements == null) {
            if (other.elements != null)
                return false;
        } else if (!elements.equals(other.elements))
            return false;
        return true;
    }

    /**
     * Evaluates the {@code subExpressionValues} against the expression, returning true if the values
     * evaluate to true for the expression, else false.
     * 
     * @throws IllegalArgumentException if any of the expected sub-expressions cannot be found in
     *           {@code subExpressionValues}
     */
    public boolean evaluate(Map<AlarmSubExpression, Boolean> subExpressionValues) {
        Stack<Object> stack = new Stack<Object>();

        for (Object element : elements) {
            if (element instanceof AlarmSubExpression) {
                Boolean value = subExpressionValues.get(element);
                if (value == null)
                    throw new IllegalArgumentException("Expected sub-expression was not found for " + element);
                stack.push(value);
            } else {
                BooleanOperator operator = (BooleanOperator) element;
                Boolean operandA = (Boolean) stack.pop();
                Boolean operandB = (Boolean) stack.pop();
                stack.push(operator.evaluate(operandA, operandB));
            }
        }

        return (Boolean) stack.pop();
    }

    /**
     * Returns the alarm's expression.
     */
    @JsonIgnore
    public String getExpression() {
        return expression;
    }

    /** Returns a boolean tree representation of the alarm expression. */
    @JsonIgnore
    public Object getExpressionTree() {
        Stack<Object> stack = new Stack<Object>();

        for (Object element : elements) {
            if (element instanceof AlarmSubExpression) {
                stack.push(element);
            } else {
                BooleanOperator operator = (BooleanOperator) element;
                Object operandA = stack.pop();
                Object operandB = stack.pop();
                BooleanExpression expr = null;
                if (operandB instanceof BooleanExpression
                        && ((BooleanExpression) operandB).operator.equals(operator)) {
                    expr = (BooleanExpression) operandB;
                    expr.operands.add(operandA);
                } else
                    expr = new BooleanExpression(operator, operandB, operandA);
                stack.push(expr);
            }
        }

        return stack.pop();
    }

    /**
     * Returns the sub expressions for the expression in the order that they appear.
     */
    public List<AlarmSubExpression> getSubExpressions() {
        if (subExpressions != null)
            return subExpressions;
        List<AlarmSubExpression> subExpressions = new ArrayList<AlarmSubExpression>();
        for (Object element : elements)
            if (element instanceof AlarmSubExpression)
                subExpressions.add((AlarmSubExpression) element);
        this.subExpressions = subExpressions;
        return subExpressions;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((elements == null) ? 0 : elements.hashCode());
        return result;
    }

    @Override
    public String toString() {
        return String.format("AlarmExpression [elements=%s]", elements);
    }
}