selector.java
来自「OpenJMS是一个开源的Java Message Service API 1.」· Java 代码 · 共 272 行
JAVA
272 行
/** * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "Exolab" must not be used to endorse or promote * products derived from this Software without prior written * permission of Exoffice Technologies. For written permission, * please contact info@exolab.org. * * 4. Products derived from this Software may not be called "Exolab" * nor may "Exolab" appear in their names without prior written * permission of Exoffice Technologies. Exolab is a registered * trademark of Exoffice Technologies. * * 5. Due credit should be given to the Exolab Project * (http://www.exolab.org/). * * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000-2001,2003 (C) Exoffice Technologies Inc. All Rights Reserved. */package org.exolab.jms.selector;import java.io.StringReader;import javax.jms.InvalidSelectorException;import javax.jms.Message;import org.exolab.jms.selector.parser.SelectorLexer;import org.exolab.jms.selector.parser.SelectorParser;import org.exolab.jms.selector.parser.SelectorTreeParser;/** * This class enables messages to be filtered using a message selector. * This is a String whose syntax is based on a subset of the SQL92 * conditional expression syntax. * * A selector can contain: * <ul> * <li>Literals:</li> * <ul> * <li>A string literal is enclosed in single quotes with an included * single quote represented by doubled single quote such as 'literal' * and 'literal''s'; like Java <i>String</i> literals these use the * unicode character encoding. * </li> * <li>An exact numeric literal is a numeric value without a decimal point * such as 57, -957, +62; numbers in the range of Java <i>long</i> are * supported. Exact numeric literals use the Java integer literal syntax. * </li> * <li>An approximate numeric literal is a numeric value in scientific * notation such as 7E3, -57.9E2 or a numeric value with a decimal such * as 7., -95.7, +6.2; numbers in the range of Java <i>double</i> * are supported. Approximate literals use the Java floating point * literal syntax. * </li> * <li>The boolean literals <i>TRUE </i>and <i>FALSE</i>.</li> * </ul> * <li>Identifiers:</li> * <ul> * <li>Identifiers use the Java identifier syntax. They are case sensitive. * </li> * <li>Identifiers cannot be the names <i>NULL</i>, <i>TRUE</i>, or * <i>FALSE</i>. * </li> * <li>Identifiers cannot be <i>NOT, AND, OR, BETWEEN, LIKE, IN</i>, and * <i>IS</i>. * </li> * <li>Identifiers are either header field references or property references. * </li> * <br>Message header field references are restricted to * <i>JMSDeliveryMode</i>, <i>JMSPriority</i>, <i>JMSMessageID</i>, * <i>JMSTimestamp</i>, <i>JMSCorrelationID</i>, and <i>JMSType</i>. * <i>JMSMessageID</i>, <i>JMSCorrelationID</i>, and <i>JMSType</i> * values may be <i>null</i> and if so are treated as a NULL value. * <li>Any name beginning with 'JMSX' is a JMS defined property name.</li> * <li>Any name beginning with 'JMS_' is a provider-specific property name. * </li> * <li>Any name that does not begin with 'JMS' is an application-specific * property name. If a property is referenced that does not exist in a * message its value is NULL. If it does exist, its value is the * corresponding property value. * </li> * </ul> * <li>Expressions:</li> * <ul> * <li>A selector is a conditional expression; a selector that evaluates to * true matches; a selector that evaluates to false or unknown does not * match. * </li> * <li>Arithmetic expressions are composed of themselves, arithmetic * operations, identifiers with numeric values and numeric literals. * </li> * <li>Conditional expressions are composed of themselves, comparison * operations, logical operations, identifiers with boolean values and * boolean literals. * </li> * <li>Standard bracketing () for ordering expression evaluation is * supported. * </li> * <li>Logical operators in precedence order: NOT, AND, OR.</li> * <li>Comparison operators: =, >, >=, <, <=, <> (not equal). * </li> * <li>Only <i>like </i>type values can be compared. One exception is that it * is valid to compare exact numeric values and approximate numeric * values (the type conversion required is defined by the rules of Java * numeric promotion). If the comparison of non-like type values is * attempted, the selector is always false. * </li> * <li><i>String</i> and <i>Boolean</i> comparison is restricted to = and * <>. Two strings are equal if and only if they contain the same * sequence of characters. * </li> * </ul> * <li>Arithmetic operators in precedence order:</li> * <ul> * <li>+, - unary</li> * <li>*, / multiplication and division</li> * <li>+, - addition and subtraction</li> * <li>Arithmetic operations use Java numeric promotion.</li> * </ul> * * <li><i>arithmetic-expr1 </i>[NOT] BETWEEN <i>arithmetic-expr2 </i>AND<i> * arithmetic-expr3</i> comparison operator * </li> * <ul> * <li>age BETWEEN 15 and 19 is equivalent to age >= 15 AND age <= 19 * </li> * <li>age NOT BETWEEN 15 and 19 is equivalent to age < 15 OR age > 19 * </li> * </ul> * <li><i>identifier </i>[NOT] IN (<i>string-literal1, string-literal2,... * </i>) * </li> * <br>comparison operator where identifier has a <i>String</i> or NULL * value. * <ul> * <li>Country IN ('UK', 'US', 'France') is true for 'UK' and false for * 'Peru'. It is equivalent to the expression (Country = ' UK') OR * (Country = ' US') OR (Country = ' France') * </li> * <li>Country NOT IN (' UK', 'US', 'France') is false for 'UK' and true * for 'Peru'. It is equivalent to the expression NOT ((Country = 'UK') * OR (Country = 'US') OR (Country = 'France')) * </li> * <li>If <i>identifier </i>of an IN or NOT IN operation is NULL the value * of the operation is unknown. * </li> * </ul> * <li><i>identifier </i>[NOT] LIKE <i>pattern-value</i> [ESCAPE * <i>escape-character</i>] * </li> * <br>comparison operator, where <i>identifier</i> has a <i>String</i> * value; <i>pattern-value</i> is a string literal where '_' stands for * any single character; '%' stands for any sequence of characters * (including the empty sequence); and all other characters stand for * themselves. The optional <i>escape-character</i> is a single character * string literal whose character is used to escape the special meaning * of the '_' and '%' in <i>pattern-value</i>. * <ul> * <li><i>phone LIKE '12%3'</i> is true for '123', '12993' and false for * '1234' * </li> * <li><i>word LIKE 'l_se'</i> is true for 'lose' and false for 'loose' * </li> * <li><i>underscored LIKE '\_%' ESCAPE '\'</i> is true for '_foo' and * false for 'bar' * </li> * <li><i>phone NOT LIKE '12%3'</i> is false for '123' and '12993' and * true for '1234' * </li> * <li>If <i>identifier</i> of a LIKE or NOT LIKE operation is NULL the * value of the operation is unknown. * </li> * </ul> * <li><i>identifier</i> IS NULL</li> * <br>comparison operator tests for a null header field value, or a * missing property value. * <ul> * <li><i>prop_name</i> IS NULL</li> * <li><i>identifier</i> IS NOT NULL comparison operator tests for the * existence of a non null header field value or property value. * </li> * <li><i>prop_name</i> IS NOT NULL</li> * </ul> * </ul></ul> * * @version $Revision: 1.1 $ $Date: 2004/11/26 01:50:44 $ * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> */public class Selector { /** * The 'compiled' expression */ private final Expression _evaluator; /** * Construct a message selector that selects messages based on the * supplied expression. * * @param expression the conditional expression * @throws InvalidSelectorException if expression is invalid */ public Selector(final String expression) throws InvalidSelectorException { try { if (expression == null || expression.length() == 0) { // always return true for null or empty expressions _evaluator = Literal.booleanLiteral(true); } else { SelectorLexer lexer = new SelectorLexer( new StringReader(expression)); lexer.initialise(); SelectorParser parser = new SelectorParser(lexer); parser.initialise(); parser.selector(); // start parsing at the selector rule SelectorTreeParser builder = new SelectorTreeParser(); builder.initialise(new DefaultExpressionFactory()); _evaluator = builder.selector(parser.getAST()); } } catch (Exception exception) { throw new InvalidSelectorException(exception.toString()); } } /** * Return if message is selected by the expression * * @param message the message * @return <code>true</code> if the message is selected, otherwise * <code>false</code> */ public boolean selects(final Message message) { boolean result = false; try { SObject value = _evaluator.evaluate(message); if (value instanceof SBool) { result = ((SBool) value).value(); } } catch (TypeMismatchException ignore) { } return result; }} //-- Selector
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?