001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.node.policy;
020
021import org.jppf.utils.PropertiesCollection;
022
023/**
024 * An execution policy rule that encapsulates a test of type <i>{@code property_value_or_expression equals a}</i>.
025 * The test applies to numeric, string or boolean values or expressions.
026 * @author Laurent Cohen
027 */
028public class Equal extends LeftOperandRule {
029  /**
030   * Explicit serialVersionUID.
031   */
032  private static final long serialVersionUID = 1L;
033  /**
034   * A numeric value to compare with.
035   */
036  private Expression<Double> numberValue;
037  /**
038   * A string value to compare with.
039   */
040  private Expression<String> stringValue;
041  /**
042   * An object value to compare with.
043   */
044  private Expression<Boolean> booleanValue;
045  /**
046   * Determines if the comparison should ignore the string case.
047   */
048  private boolean ignoreCase;
049
050  /**
051   * Define an equality comparison between the numeric value of a property and another numeric value.<br>
052   * Note that if the value type is equal to {@link ValueType#STRING}, then the comparison will be case-insensitive.
053   * To specify case sensitivity, use the {@link #Equal(String, boolean, String)} constructor instead.
054   * @param valueType the type of value to which thie equality comparison applies. 
055   * @param propertyNameOrExpression either a literal string which represents a property name, or an expression resolving to a numeric value.
056   * @param a the value to compare with.
057   */
058  public Equal(final ValueType valueType, final String propertyNameOrExpression, final String a) {
059    super(valueType, propertyNameOrExpression);
060    switch(valueType) {
061      case BOOLEAN:
062        this.booleanValue = new BooleanExpression(a);
063        break;
064
065      case NUMERIC:
066        this.numberValue = new NumericExpression(a);
067        break;
068
069      case STRING:
070        this.stringValue = new StringExpression(a);
071        break;
072    }
073  }
074
075  /**
076   * Define an equality comparison between the numeric value of a property and another numeric value.
077   * @param propertyNameOrExpression either a literal string which represents a property name, or an expression resolving to a numeric value.
078   * @param a the value to compare with.
079   */
080  public Equal(final String propertyNameOrExpression, final double a) {
081    super(ValueType.NUMERIC, propertyNameOrExpression);
082    this.numberValue = new NumericExpression(a);
083  }
084
085  /**
086   * Define an equality comparison between the string value of a property and another string value.
087   * @param propertyNameOrExpression either a literal string which represents a property name, or an expression resolving to a string value.
088   * @param ignoreCase determines if the comparison should ignore the string case.
089   * @param a the value to compare with.
090   */
091  public Equal(final String propertyNameOrExpression, final boolean ignoreCase, final String a) {
092    super(ValueType.STRING, propertyNameOrExpression);
093    this.stringValue = new StringExpression(a);
094    this.ignoreCase = ignoreCase;
095  }
096
097  /**
098   * Define an equality comparison between the boolean value of a property and another boolean value.
099   * @param propertyNameOrExpression either a literal string which represents a property name, or an expression resolving to a boolean value.
100   * @param a the value to compare with.
101   */
102  public Equal(final String propertyNameOrExpression, final boolean a) {
103    super(ValueType.BOOLEAN, propertyNameOrExpression);
104    this.booleanValue = new BooleanExpression(a);
105  }
106
107  /**
108   * Determines whether this policy accepts the specified node.
109   * @param info system information for the node on which the tasks will run if accepted.
110   * @return true if the node is accepted, false otherwise.
111   */
112  @Override
113  public boolean accepts(final PropertiesCollection<String> info) {
114    final Object o = getLeftOperandValue(info);
115    if (numberValue != null) return (o == null) ? false : o.equals(numberValue.evaluate(info));
116    else if (stringValue != null) return ignoreCase ? stringValue.evaluate(info).equalsIgnoreCase((String) o) : stringValue.evaluate(info).equals(o);
117    else if (booleanValue != null) return (o == null) ? false : o.equals(booleanValue.evaluate(info));
118    else return o == null;
119  }
120
121  @Override
122  public String toString(final int n) {
123    final StringBuilder sb = new StringBuilder(indent(n)).append("<Equal valueType=\"");
124    if (stringValue != null) sb.append("string");
125    else if (numberValue != null) sb.append("numeric");
126    else if (booleanValue != null) sb.append("boolean");
127    sb.append("\" ignoreCase=\"").append(ignoreCase).append("\">\n");
128    sb.append(indent(n + 1)).append("<Property>").append(leftOperand.getExpression()).append("</Property>\n");
129    sb.append(indent(n + 1)).append("<Value>");
130    if (stringValue != null) sb.append(stringValue.getExpression());
131    else if (numberValue != null) sb.append(numberValue.getExpression());
132    else if (booleanValue != null) sb.append(booleanValue.getExpression());
133    sb.append("</Value>\n");
134    sb.append(indent(n)).append("</Equal>\n");
135    return sb.toString();
136  }
137}