mirror of
https://github.com/apache/activemq-artemis.git
synced 2025-02-08 11:05:34 +00:00
This closes #4194
This commit is contained in:
commit
9a0669e282
@ -221,6 +221,9 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
|
|||||||
|
|
||||||
// Iff one of the values is null
|
// Iff one of the values is null
|
||||||
if (lv == null ^ rv == null) {
|
if (lv == null ^ rv == null) {
|
||||||
|
if (lv == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return Boolean.FALSE;
|
return Boolean.FALSE;
|
||||||
}
|
}
|
||||||
if (lv == rv || lv.equals(rv)) {
|
if (lv == rv || lv.equals(rv)) {
|
||||||
@ -232,6 +235,31 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
|
|||||||
return Boolean.FALSE;
|
return Boolean.FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Filterable message) throws FilterException {
|
||||||
|
Object lv = left.evaluate(message);
|
||||||
|
Object rv = right.evaluate(message);
|
||||||
|
|
||||||
|
// If one of the values is null
|
||||||
|
if (lv == null ^ rv == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (lv == rv || lv.equals(rv)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (lv.getClass() == rv.getClass()) {
|
||||||
|
// same class, but 'equals' return false, and they are not the same object
|
||||||
|
// there is no point in doing 'compare'
|
||||||
|
// this case happens often while comparing non equals Strings
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (lv instanceof Comparable && rv instanceof Comparable) {
|
||||||
|
Boolean compareResult = compare((Comparable) lv, (Comparable) rv);
|
||||||
|
return compareResult != null && compareResult;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean asBoolean(int answer) {
|
protected boolean asBoolean(int answer) {
|
||||||
return answer == 0;
|
return answer == 0;
|
||||||
|
@ -16,78 +16,170 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.activemq.artemis.selector.filter;
|
package org.apache.activemq.artemis.selector.filter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A filter performing a comparison of two objects
|
* A sequence of expressions, to be combined with OR or AND conjunctions.
|
||||||
*
|
*
|
||||||
* @version $Revision: 1.2 $
|
|
||||||
*/
|
*/
|
||||||
public abstract class LogicExpression extends BinaryExpression implements BooleanExpression {
|
public abstract class LogicExpression implements BooleanExpression {
|
||||||
|
|
||||||
|
protected final List<BooleanExpression> expressions = new ArrayList<>(2);
|
||||||
|
|
||||||
|
private LogicExpression(BooleanExpression lvalue, BooleanExpression rvalue) {
|
||||||
|
expressions.add(lvalue);
|
||||||
|
expressions.add(rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addExpression(BooleanExpression expression) {
|
||||||
|
expressions.add(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanExpression getLeft() {
|
||||||
|
if (expressions.size() == 2) {
|
||||||
|
return expressions.get(0);
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("This expression is not binary: " + this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanExpression getRight() {
|
||||||
|
if (expressions.size() == 2) {
|
||||||
|
return expressions.get(1);
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("This expression is not binary: " + this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param left
|
* Returns the symbol that represents this binary expression. For example, addition is
|
||||||
* @param right
|
* represented by "+"
|
||||||
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
public LogicExpression(BooleanExpression left, BooleanExpression right) {
|
public abstract String getExpressionSymbol();
|
||||||
super(left, right);
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (expressions.size() == 2) {
|
||||||
|
return "( " + expressions.get(0) + " " + getExpressionSymbol() + " " + expressions.get(1) + " )";
|
||||||
|
}
|
||||||
|
StringBuilder result = new StringBuilder("(");
|
||||||
|
int count = 0;
|
||||||
|
for (BooleanExpression expression : expressions) {
|
||||||
|
if (count++ > 0) {
|
||||||
|
result.append(" " + getExpressionSymbol() + " ");
|
||||||
|
}
|
||||||
|
result.append(expression.toString());
|
||||||
|
}
|
||||||
|
result.append(")");
|
||||||
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BooleanExpression createOR(BooleanExpression lvalue, BooleanExpression rvalue) {
|
public static BooleanExpression createOR(BooleanExpression lvalue, BooleanExpression rvalue) {
|
||||||
return new LogicExpression(lvalue, rvalue) {
|
if (lvalue instanceof ORExpression) {
|
||||||
|
ORExpression orExpression = (ORExpression) lvalue;
|
||||||
@Override
|
orExpression.addExpression(rvalue);
|
||||||
public Object evaluate(Filterable message) throws FilterException {
|
return orExpression;
|
||||||
|
} else {
|
||||||
Boolean lv = (Boolean) left.evaluate(message);
|
return new ORExpression(lvalue, rvalue);
|
||||||
// Can we do an OR shortcut??
|
}
|
||||||
if (lv != null && lv.booleanValue()) {
|
|
||||||
return Boolean.TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean rv = (Boolean) right.evaluate(message);
|
|
||||||
return rv == null ? null : rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getExpressionSymbol() {
|
|
||||||
return "OR";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BooleanExpression createAND(BooleanExpression lvalue, BooleanExpression rvalue) {
|
public static BooleanExpression createAND(BooleanExpression lvalue, BooleanExpression rvalue) {
|
||||||
return new LogicExpression(lvalue, rvalue) {
|
if (lvalue instanceof ANDExpression) {
|
||||||
|
ANDExpression orExpression = (ANDExpression) lvalue;
|
||||||
@Override
|
orExpression.addExpression(rvalue);
|
||||||
public Object evaluate(Filterable message) throws FilterException {
|
return orExpression;
|
||||||
|
} else {
|
||||||
Boolean lv = (Boolean) left.evaluate(message);
|
return new ANDExpression(lvalue, rvalue);
|
||||||
|
}
|
||||||
// Can we do an AND shortcut??
|
|
||||||
if (lv == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!lv.booleanValue()) {
|
|
||||||
return Boolean.FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean rv = (Boolean) right.evaluate(message);
|
|
||||||
return rv == null ? null : rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getExpressionSymbol() {
|
|
||||||
return "AND";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract Object evaluate(Filterable message) throws FilterException;
|
public abstract Object evaluate(Filterable message) throws FilterException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(Filterable message) throws FilterException {
|
public abstract boolean matches(Filterable message) throws FilterException;
|
||||||
Object object = evaluate(message);
|
|
||||||
return object == Boolean.TRUE;
|
private static class ORExpression extends LogicExpression {
|
||||||
|
|
||||||
|
ORExpression(BooleanExpression lvalue, BooleanExpression rvalue) {
|
||||||
|
super(lvalue, rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object evaluate(Filterable message) throws FilterException {
|
||||||
|
boolean someNulls = false;
|
||||||
|
for (BooleanExpression expression : expressions) {
|
||||||
|
Boolean lv = (Boolean)expression.evaluate(message);
|
||||||
|
if (lv != null && lv.booleanValue()) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
if (lv == null) {
|
||||||
|
someNulls = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (someNulls) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Filterable message) throws FilterException {
|
||||||
|
for (BooleanExpression expression : expressions) {
|
||||||
|
boolean lv = expression.matches(message);
|
||||||
|
if (lv) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExpressionSymbol() {
|
||||||
|
return "OR";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ANDExpression extends LogicExpression {
|
||||||
|
|
||||||
|
ANDExpression(BooleanExpression lvalue, BooleanExpression rvalue) {
|
||||||
|
super(lvalue, rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object evaluate(Filterable message) throws FilterException {
|
||||||
|
boolean someNulls = false;
|
||||||
|
for (BooleanExpression expression : expressions) {
|
||||||
|
Boolean lv = (Boolean)expression.evaluate(message);
|
||||||
|
if (lv != null && !lv.booleanValue()) {
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
if (lv == null) {
|
||||||
|
someNulls = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (someNulls) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Filterable message) throws FilterException {
|
||||||
|
for (BooleanExpression expression : expressions) {
|
||||||
|
boolean lv = expression.matches(message);
|
||||||
|
if (!lv) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExpressionSymbol() {
|
||||||
|
return "AND";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,16 @@ public abstract class UnaryExpression implements Expression {
|
|||||||
return !lvalue.booleanValue();
|
return !lvalue.booleanValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Filterable message) throws FilterException {
|
||||||
|
Boolean lvalue = (Boolean) right.evaluate(message);
|
||||||
|
if (lvalue == null) {
|
||||||
|
// NOT NULL returns NULL that eventually fails the selector
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !lvalue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getExpressionSymbol() {
|
public String getExpressionSymbol() {
|
||||||
return "NOT";
|
return "NOT";
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.activemq.artemis.selector;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||||
|
import org.apache.activemq.artemis.selector.filter.FilterException;
|
||||||
|
import org.apache.activemq.artemis.selector.filter.Filterable;
|
||||||
|
|
||||||
|
public class MockMessage implements Filterable {
|
||||||
|
|
||||||
|
HashMap<String, Object> properties = new HashMap<>();
|
||||||
|
private String text;
|
||||||
|
private Object destination;
|
||||||
|
private String messageId;
|
||||||
|
private String type;
|
||||||
|
private Object localConnectionId;
|
||||||
|
|
||||||
|
public void setDestination(Object destination) {
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJMSMessageID(String messageId) {
|
||||||
|
this.messageId = messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJMSType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBooleanProperty(String key, boolean value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringProperty(String key, String value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setByteProperty(String key, byte value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoubleProperty(String key, double value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFloatProperty(String key, float value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongProperty(String key, long value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntProperty(String key, int value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShortProperty(String key, short value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObjectProperty(String key, Object value) {
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getBodyAs(Class<T> type) throws FilterException {
|
||||||
|
if (type == String.class) {
|
||||||
|
return type.cast(text);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getProperty(SimpleString name) {
|
||||||
|
String stringName = name.toString();
|
||||||
|
if ("JMSType".equals(stringName)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
if ("JMSMessageID".equals(stringName)) {
|
||||||
|
return messageId;
|
||||||
|
}
|
||||||
|
return properties.get(stringName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getLocalConnectionId() {
|
||||||
|
return localConnectionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,117 +16,24 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.activemq.artemis.selector;
|
package org.apache.activemq.artemis.selector;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
|
||||||
import org.apache.activemq.artemis.selector.filter.BooleanExpression;
|
import org.apache.activemq.artemis.selector.filter.BooleanExpression;
|
||||||
import org.apache.activemq.artemis.selector.filter.FilterException;
|
import org.apache.activemq.artemis.selector.filter.FilterException;
|
||||||
import org.apache.activemq.artemis.selector.filter.Filterable;
|
|
||||||
import org.apache.activemq.artemis.selector.impl.SelectorParser;
|
import org.apache.activemq.artemis.selector.impl.SelectorParser;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class SelectorTest {
|
public class SelectorTest {
|
||||||
|
|
||||||
class MockMessage implements Filterable {
|
|
||||||
|
|
||||||
HashMap<String, Object> properties = new HashMap<>();
|
|
||||||
private String text;
|
|
||||||
private Object destination;
|
|
||||||
private String messageId;
|
|
||||||
private String type;
|
|
||||||
private Object localConnectionId;
|
|
||||||
|
|
||||||
public void setDestination(Object destination) {
|
|
||||||
this.destination = destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJMSMessageID(String messageId) {
|
|
||||||
this.messageId = messageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJMSType(String type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setText(String text) {
|
|
||||||
this.text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBooleanProperty(String key, boolean value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStringProperty(String key, String value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setByteProperty(String key, byte value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDoubleProperty(String key, double value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFloatProperty(String key, float value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLongProperty(String key, long value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIntProperty(String key, int value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShortProperty(String key, short value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setObjectProperty(String key, Object value) {
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T getBodyAs(Class<T> type) throws FilterException {
|
|
||||||
if (type == String.class) {
|
|
||||||
return type.cast(text);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getProperty(SimpleString name) {
|
|
||||||
String stringName = name.toString();
|
|
||||||
if ("JMSType".equals(stringName)) {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
if ("JMSMessageID".equals(stringName)) {
|
|
||||||
return messageId;
|
|
||||||
}
|
|
||||||
return properties.get(stringName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getDestination() {
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getLocalConnectionId() {
|
|
||||||
return localConnectionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBooleanSelector() throws Exception {
|
public void testBooleanSelector() throws Exception {
|
||||||
MockMessage message = createMessage();
|
MockMessage message = createMessage();
|
||||||
|
|
||||||
assertSelector(message, "(trueProp OR falseProp) AND trueProp", true);
|
assertSelector(message, "(trueProp OR falseProp) AND trueProp", true);
|
||||||
assertSelector(message, "(trueProp OR falseProp) AND falseProp", false);
|
assertSelector(message, "(trueProp OR falseProp) AND falseProp", false);
|
||||||
|
assertSelector(message, "(falseProp OR falseProp OR falseProp OR falseProp OR falseProp OR falseProp OR trueProp)", true);
|
||||||
|
assertSelector(message, "(falseProp OR falseProp OR falseProp OR falseProp OR falseProp OR falseProp OR falseProp)", false);
|
||||||
|
assertSelector(message, "(trueProp AND trueProp AND trueProp AND trueProp AND trueProp AND trueProp AND falseProp)", false);
|
||||||
|
assertSelector(message, "(trueProp AND trueProp AND trueProp AND trueProp AND trueProp AND trueProp AND trueProp)", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -0,0 +1,175 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.activemq.artemis.selector;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.selector.filter.BooleanExpression;
|
||||||
|
import org.apache.activemq.artemis.selector.filter.FilterException;
|
||||||
|
import org.apache.activemq.artemis.selector.impl.SelectorParser;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class UnknownHandlingSelectorTest {
|
||||||
|
|
||||||
|
private MockMessage message;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
message = new MockMessage();
|
||||||
|
message.setDestination("FOO.BAR");
|
||||||
|
message.setJMSType("selector-test");
|
||||||
|
message.setJMSMessageID("connection:1:1:1:1");
|
||||||
|
message.setBooleanProperty("trueProp", true);
|
||||||
|
message.setBooleanProperty("falseProp", false);
|
||||||
|
message.setObjectProperty("nullProp", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* | NOT
|
||||||
|
* +------+------
|
||||||
|
* | T | F
|
||||||
|
* | F | T
|
||||||
|
* | U | U
|
||||||
|
* +------+-------
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void notEvaluation() throws Exception {
|
||||||
|
assertSelector("not(trueProp)", false);
|
||||||
|
assertSelector("not(falseProp)", true);
|
||||||
|
assertSelector("not(unknownProp)", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* | AND | T | F | U
|
||||||
|
* +------+-------+-------+-------
|
||||||
|
* | T | T | F | U
|
||||||
|
* | F | F | F | F
|
||||||
|
* | U | U | F | U
|
||||||
|
* +------+-------+-------+-------
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void andEvaluation() throws Exception {
|
||||||
|
assertSelectorEvaluatesToTrue("trueProp AND trueProp");
|
||||||
|
assertSelectorEvaluatesToFalse("trueProp AND falseProp");
|
||||||
|
assertSelectorEvaluatesToFalse("falseProp AND trueProp");
|
||||||
|
assertSelectorEvaluatesToFalse("falseProp AND falseProp");
|
||||||
|
assertSelectorEvaluatesToFalse("falseProp AND unknownProp");
|
||||||
|
assertSelectorEvaluatesToFalse("unknownProp AND falseProp");
|
||||||
|
assertSelectorEvaluatesToUnknown("trueProp AND unknownProp");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp AND trueProp");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp AND unknownProp");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* | OR | T | F | U
|
||||||
|
* +------+-------+-------+--------
|
||||||
|
* | T | T | T | T
|
||||||
|
* | F | T | F | U
|
||||||
|
* | U | T | U | U
|
||||||
|
* +------+-------+-------+-------
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void orEvaluation() throws Exception {
|
||||||
|
assertSelectorEvaluatesToTrue("trueProp OR trueProp");
|
||||||
|
assertSelectorEvaluatesToTrue("trueProp OR falseProp");
|
||||||
|
assertSelectorEvaluatesToTrue("falseProp OR trueProp");
|
||||||
|
assertSelectorEvaluatesToTrue("trueProp OR unknownProp");
|
||||||
|
assertSelectorEvaluatesToTrue("unknownProp OR trueProp");
|
||||||
|
assertSelectorEvaluatesToFalse("falseProp OR falseProp");
|
||||||
|
assertSelectorEvaluatesToUnknown("falseProp OR unknownProp");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp OR falseProp");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp OR unknownProp");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void comparisonWithUnknownShouldEvaluateToUnknown() throws Exception {
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp = 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp > 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp >= 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp < 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp <= 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp <> 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp LIKE 'zero'");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp NOT LIKE 'zero'");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp IN ('zero')");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp NOT IN ('zero')");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp BETWEEN 1 AND 2");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp NOT BETWEEN 1 AND 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void comparisonWithNullPropShouldEvaluateToUnknown() throws Exception {
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp = 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp > 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp >= 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp < 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp <= 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp <> 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp LIKE 'zero'");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp NOT LIKE 'zero'");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp IN ('zero')");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp NOT IN ('zero')");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp BETWEEN 1 AND 2");
|
||||||
|
assertSelectorEvaluatesToUnknown("nullProp NOT BETWEEN 1 AND 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isNullIsNotNull() throws Exception {
|
||||||
|
assertSelectorEvaluatesToTrue("unknownProp IS NULL");
|
||||||
|
assertSelectorEvaluatesToTrue("nullProp IS NULL");
|
||||||
|
assertSelectorEvaluatesToFalse("trueProp IS NULL");
|
||||||
|
assertSelectorEvaluatesToFalse("unknownProp IS NOT NULL");
|
||||||
|
assertSelectorEvaluatesToFalse("nullProp IS NOT NULL");
|
||||||
|
assertSelectorEvaluatesToTrue("trueProp IS NOT NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void arithmeticWithNull() throws Exception {
|
||||||
|
assertSelectorEvaluatesToUnknown("-unknownProp = 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("+unknownProp = 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp * 2 = 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp / 2 = 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp + 2 = 0");
|
||||||
|
assertSelectorEvaluatesToUnknown("unknownProp - 2 = 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertSelectorEvaluatesToUnknown(String selector) throws FilterException {
|
||||||
|
assertSelector(selector, false);
|
||||||
|
assertSelector(not(selector), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertSelectorEvaluatesToTrue(String selector) throws FilterException {
|
||||||
|
assertSelector(selector, true);
|
||||||
|
assertSelector(not(selector), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertSelectorEvaluatesToFalse(String selector) throws FilterException {
|
||||||
|
assertSelector(selector, false);
|
||||||
|
assertSelector(not(selector), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertSelector(String text, boolean expected) throws FilterException {
|
||||||
|
BooleanExpression selector = SelectorParser.parse(text);
|
||||||
|
Assert.assertTrue("Created a valid selector", selector != null);
|
||||||
|
boolean value = selector.matches(message);
|
||||||
|
Assert.assertEquals("Selector for: " + text, expected, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String not(String selector) {
|
||||||
|
return "not(" + selector + ")";
|
||||||
|
}
|
||||||
|
}
|
@ -251,29 +251,31 @@ public class ClusterConnectionBridge extends BridgeImpl {
|
|||||||
|
|
||||||
SimpleString notifQueueName = new SimpleString(qName);
|
SimpleString notifQueueName = new SimpleString(qName);
|
||||||
|
|
||||||
SimpleString filter = new SimpleString(ManagementHelper.HDR_BINDING_TYPE + "<>" +
|
SimpleString filter = new SimpleString("(" + ManagementHelper.HDR_BINDING_TYPE + " <> " + BindingType.DIVERT.toInt() +
|
||||||
BindingType.DIVERT.toInt() +
|
" OR "
|
||||||
|
+ ManagementHelper.HDR_BINDING_TYPE + " IS NULL)" +
|
||||||
" AND " +
|
" AND " +
|
||||||
ManagementHelper.HDR_NOTIFICATION_TYPE +
|
ManagementHelper.HDR_NOTIFICATION_TYPE +
|
||||||
" IN ('" +
|
" IN ('" +
|
||||||
CoreNotificationType.SESSION_CREATED +
|
CoreNotificationType.SESSION_CREATED +
|
||||||
"','" +
|
"', '" +
|
||||||
CoreNotificationType.BINDING_ADDED +
|
CoreNotificationType.BINDING_ADDED +
|
||||||
"','" +
|
"', '" +
|
||||||
CoreNotificationType.BINDING_REMOVED +
|
CoreNotificationType.BINDING_REMOVED +
|
||||||
"','" +
|
"', '" +
|
||||||
CoreNotificationType.CONSUMER_CREATED +
|
CoreNotificationType.CONSUMER_CREATED +
|
||||||
"','" +
|
"', '" +
|
||||||
CoreNotificationType.CONSUMER_CLOSED +
|
CoreNotificationType.CONSUMER_CLOSED +
|
||||||
"','" +
|
"', '" +
|
||||||
CoreNotificationType.PROPOSAL +
|
CoreNotificationType.PROPOSAL +
|
||||||
"','" +
|
"', '" +
|
||||||
CoreNotificationType.PROPOSAL_RESPONSE +
|
CoreNotificationType.PROPOSAL_RESPONSE +
|
||||||
"','" +
|
"', '" +
|
||||||
CoreNotificationType.UNPROPOSAL +
|
CoreNotificationType.UNPROPOSAL +
|
||||||
"') AND " +
|
"')" +
|
||||||
|
" AND " +
|
||||||
ManagementHelper.HDR_DISTANCE +
|
ManagementHelper.HDR_DISTANCE +
|
||||||
"<" +
|
" < " +
|
||||||
flowRecord.getMaxHops() +
|
flowRecord.getMaxHops() +
|
||||||
" AND (" +
|
" AND (" +
|
||||||
createSelectorFromAddress(appendIgnoresToFilter(flowRecord.getAddress())) +
|
createSelectorFromAddress(appendIgnoresToFilter(flowRecord.getAddress())) +
|
||||||
|
@ -170,9 +170,15 @@ public class FilterTest extends SilentTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testDifferentNullString() throws Exception {
|
public void testDifferentNullString() throws Exception {
|
||||||
filter = FilterImpl.createFilter(new SimpleString("prop <> 'foo'"));
|
filter = FilterImpl.createFilter(new SimpleString("prop <> 'foo'"));
|
||||||
|
Assert.assertFalse(filter.match(message));
|
||||||
|
|
||||||
|
filter = FilterImpl.createFilter(new SimpleString("prop <> 'foo' OR prop IS NULL"));
|
||||||
Assert.assertTrue(filter.match(message));
|
Assert.assertTrue(filter.match(message));
|
||||||
|
|
||||||
filter = FilterImpl.createFilter(new SimpleString("NOT (prop = 'foo')"));
|
filter = FilterImpl.createFilter(new SimpleString("NOT (prop = 'foo')"));
|
||||||
|
Assert.assertFalse(filter.match(message));
|
||||||
|
|
||||||
|
filter = FilterImpl.createFilter(new SimpleString("NOT (prop = 'foo') OR prop IS NULL"));
|
||||||
Assert.assertTrue(filter.match(message));
|
Assert.assertTrue(filter.match(message));
|
||||||
|
|
||||||
filter = FilterImpl.createFilter(new SimpleString("prop <> 'foo'"));
|
filter = FilterImpl.createFilter(new SimpleString("prop <> 'foo'"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user