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
|
||||
if (lv == null ^ rv == null) {
|
||||
if (lv == null) {
|
||||
return null;
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if (lv == rv || lv.equals(rv)) {
|
||||
|
@ -232,6 +235,31 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
|
|||
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
|
||||
protected boolean asBoolean(int answer) {
|
||||
return answer == 0;
|
||||
|
|
|
@ -16,78 +16,170 @@
|
|||
*/
|
||||
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
|
||||
* @param right
|
||||
* Returns the symbol that represents this binary expression. For example, addition is
|
||||
* represented by "+"
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public LogicExpression(BooleanExpression left, BooleanExpression right) {
|
||||
super(left, right);
|
||||
public abstract String getExpressionSymbol();
|
||||
|
||||
@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) {
|
||||
return new LogicExpression(lvalue, rvalue) {
|
||||
|
||||
@Override
|
||||
public Object evaluate(Filterable message) throws FilterException {
|
||||
|
||||
Boolean lv = (Boolean) left.evaluate(message);
|
||||
// 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";
|
||||
}
|
||||
};
|
||||
if (lvalue instanceof ORExpression) {
|
||||
ORExpression orExpression = (ORExpression) lvalue;
|
||||
orExpression.addExpression(rvalue);
|
||||
return orExpression;
|
||||
} else {
|
||||
return new ORExpression(lvalue, rvalue);
|
||||
}
|
||||
}
|
||||
|
||||
public static BooleanExpression createAND(BooleanExpression lvalue, BooleanExpression rvalue) {
|
||||
return new LogicExpression(lvalue, rvalue) {
|
||||
|
||||
@Override
|
||||
public Object evaluate(Filterable message) throws FilterException {
|
||||
|
||||
Boolean lv = (Boolean) left.evaluate(message);
|
||||
|
||||
// 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";
|
||||
}
|
||||
};
|
||||
if (lvalue instanceof ANDExpression) {
|
||||
ANDExpression orExpression = (ANDExpression) lvalue;
|
||||
orExpression.addExpression(rvalue);
|
||||
return orExpression;
|
||||
} else {
|
||||
return new ANDExpression(lvalue, rvalue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Object evaluate(Filterable message) throws FilterException;
|
||||
|
||||
@Override
|
||||
public boolean matches(Filterable message) throws FilterException {
|
||||
Object object = evaluate(message);
|
||||
return object == Boolean.TRUE;
|
||||
public abstract boolean matches(Filterable message) throws FilterException;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@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
|
||||
public String getExpressionSymbol() {
|
||||
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;
|
||||
|
||||
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.FilterException;
|
||||
import org.apache.activemq.artemis.selector.filter.Filterable;
|
||||
import org.apache.activemq.artemis.selector.impl.SelectorParser;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
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
|
||||
public void testBooleanSelector() throws Exception {
|
||||
MockMessage message = createMessage();
|
||||
|
||||
assertSelector(message, "(trueProp OR falseProp) AND trueProp", true);
|
||||
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
|
||||
|
|
|
@ -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 filter = new SimpleString(ManagementHelper.HDR_BINDING_TYPE + "<>" +
|
||||
BindingType.DIVERT.toInt() +
|
||||
SimpleString filter = new SimpleString("(" + ManagementHelper.HDR_BINDING_TYPE + " <> " + BindingType.DIVERT.toInt() +
|
||||
" OR "
|
||||
+ ManagementHelper.HDR_BINDING_TYPE + " IS NULL)" +
|
||||
" AND " +
|
||||
ManagementHelper.HDR_NOTIFICATION_TYPE +
|
||||
" IN ('" +
|
||||
CoreNotificationType.SESSION_CREATED +
|
||||
"','" +
|
||||
"', '" +
|
||||
CoreNotificationType.BINDING_ADDED +
|
||||
"','" +
|
||||
"', '" +
|
||||
CoreNotificationType.BINDING_REMOVED +
|
||||
"','" +
|
||||
"', '" +
|
||||
CoreNotificationType.CONSUMER_CREATED +
|
||||
"','" +
|
||||
"', '" +
|
||||
CoreNotificationType.CONSUMER_CLOSED +
|
||||
"','" +
|
||||
"', '" +
|
||||
CoreNotificationType.PROPOSAL +
|
||||
"','" +
|
||||
"', '" +
|
||||
CoreNotificationType.PROPOSAL_RESPONSE +
|
||||
"','" +
|
||||
"', '" +
|
||||
CoreNotificationType.UNPROPOSAL +
|
||||
"') AND " +
|
||||
"')" +
|
||||
" AND " +
|
||||
ManagementHelper.HDR_DISTANCE +
|
||||
"<" +
|
||||
" < " +
|
||||
flowRecord.getMaxHops() +
|
||||
" AND (" +
|
||||
createSelectorFromAddress(appendIgnoresToFilter(flowRecord.getAddress())) +
|
||||
|
|
|
@ -170,9 +170,15 @@ public class FilterTest extends SilentTestCase {
|
|||
@Test
|
||||
public void testDifferentNullString() throws Exception {
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
filter = FilterImpl.createFilter(new SimpleString("prop <> 'foo'"));
|
||||
|
|
Loading…
Reference in New Issue