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 java.io.*;
022import java.util.regex.*;
023
024import org.jppf.utils.PropertiesCollection;
025
026/**
027 * An execution policy rule that encapsulates a test of type <i>property_value matches regular_expression</i>.
028 * The expression syntax must follow the one specified for {@link java.util.regex.Pattern Pattern}.
029 * The test applies to string values only.
030 * @author Laurent Cohen
031 */
032public class RegExp extends LeftOperandRule {
033  /**
034   * Explicit serialVersionUID.
035   */
036  private static final long serialVersionUID = 1L;
037  /**
038   * A regular expression to match the property value against.
039   */
040  private String regExp;
041  /**
042   * The pattern object to compile from the regular expression.
043   */
044  private transient Pattern pattern;
045
046  /**
047   * Define an equality comparison between the string value of a property and another string value.
048   * @param propertyNameOrExpression either a literal string which represents a property name, or an expression resolving to a numeric value.
049   * @param regExp a regular expression to match the property value against.
050   * @throws PatternSyntaxException if the syntax of expression is invalid
051   */
052  public RegExp(final String propertyNameOrExpression, final String regExp) throws PatternSyntaxException {
053    super(ValueType.STRING, propertyNameOrExpression);
054    // compiled at creation time to ensure any syntax problem in the expression is known on the client side.
055    pattern = Pattern.compile(regExp);
056    this.regExp = regExp;
057  }
058
059  /**
060   * Determines whether this policy accepts the specified node.
061   * @param info system information for the node on which the tasks will run if accepted.
062   * @return true if the node is accepted, false otherwise.
063   */
064  @Override
065  public boolean accepts(final PropertiesCollection<String> info) {
066    if (regExp == null) return false;
067    final Object o = getLeftOperandValue(info);
068    if (o == null) return false;
069    return pattern.matcher((String) o).matches();
070  }
071
072  @Override
073  public String toString(final int n) {
074    return new StringBuilder(indent(n)).append("<RegExp>\n")
075      .append(indent(n + 1)).append("<Property>").append(leftOperand.getExpression()).append("</Property>\n")
076      .append(indent(n + 1)).append("<Value>").append(regExp).append("</Value>\n")
077      .append(indent(n)).append("</RegExp>\n").toString();
078  }
079
080  /**
081   * Save the state of this object to a stream (i.e.,serialize it).
082   * @param out the output stream to which to write the job. 
083   * @throws IOException if any I/O error occurs.
084   * @since 5.2
085   */
086  @SuppressWarnings("static-method")
087  private void writeObject(final ObjectOutputStream out) throws IOException {
088    out.defaultWriteObject();
089  }
090
091  /**
092   * Reconstitute this object from a stream (i.e., deserialize it).
093   * @param in the input stream from which to read the state. 
094   * @throws IOException if any I/O error occurs.
095   * @throws ClassNotFoundException if the class of an object in the object graph can not be found.
096   * @since 5.2
097   */
098  private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
099    in.defaultReadObject();
100    pattern = Pattern.compile(regExp);
101  }
102}