mirror of https://github.com/apache/activemq.git
Apply patch correctly honor JMS selector behavior for unknown values.
This commit is contained in:
parent
bf5305e2ee
commit
6e9ecdfe21
|
@ -212,6 +212,9 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
|
||||||
|
|
||||||
// If one of the values is null
|
// If 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)) {
|
||||||
|
|
|
@ -39,13 +39,17 @@ public abstract class LogicExpression extends BinaryExpression implements Boolea
|
||||||
public Object evaluate(MessageEvaluationContext message) throws JMSException {
|
public Object evaluate(MessageEvaluationContext message) throws JMSException {
|
||||||
|
|
||||||
Boolean lv = (Boolean)left.evaluate(message);
|
Boolean lv = (Boolean)left.evaluate(message);
|
||||||
// Can we do an OR shortcut??
|
|
||||||
if (lv != null && lv.booleanValue()) {
|
if (lv != null && lv.booleanValue()) {
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean rv = (Boolean)right.evaluate(message);
|
Boolean rv = (Boolean)right.evaluate(message);
|
||||||
return rv == null ? null : rv;
|
if (rv != null && rv.booleanValue()) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
if (lv == null || rv == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Boolean.FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getExpressionSymbol() {
|
public String getExpressionSymbol() {
|
||||||
|
@ -61,16 +65,17 @@ public abstract class LogicExpression extends BinaryExpression implements Boolea
|
||||||
|
|
||||||
Boolean lv = (Boolean)left.evaluate(message);
|
Boolean lv = (Boolean)left.evaluate(message);
|
||||||
|
|
||||||
// Can we do an AND shortcut??
|
if (lv != null && !lv.booleanValue()) {
|
||||||
if (lv == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!lv.booleanValue()) {
|
|
||||||
return Boolean.FALSE;
|
return Boolean.FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean rv = (Boolean)right.evaluate(message);
|
Boolean rv = (Boolean)right.evaluate(message);
|
||||||
return rv == null ? null : rv;
|
if (rv != null && !rv.booleanValue()) {
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
if (lv == null || rv == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getExpressionSymbol() {
|
public String getExpressionSymbol() {
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
/**
|
||||||
|
* 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.selector;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
import javax.jms.Message;
|
||||||
|
|
||||||
|
import org.apache.activemq.command.ActiveMQMessage;
|
||||||
|
import org.apache.activemq.command.ActiveMQTopic;
|
||||||
|
import org.apache.activemq.filter.BooleanExpression;
|
||||||
|
import org.apache.activemq.filter.MessageEvaluationContext;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class UnknownHandlingSelectorTest {
|
||||||
|
|
||||||
|
private Message message;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
message = new ActiveMQMessage();
|
||||||
|
message.setJMSDestination(new ActiveMQTopic("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 JMSException {
|
||||||
|
assertSelector(selector, false);
|
||||||
|
assertSelector(not(selector), false);
|
||||||
|
}
|
||||||
|
protected void assertSelectorEvaluatesToTrue(String selector) throws JMSException {
|
||||||
|
assertSelector(selector, true);
|
||||||
|
assertSelector(not(selector), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertSelectorEvaluatesToFalse(String selector) throws JMSException {
|
||||||
|
assertSelector(selector, false);
|
||||||
|
assertSelector(not(selector), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertSelector(String text, boolean matches) throws JMSException {
|
||||||
|
BooleanExpression selector = SelectorParser.parse(text);
|
||||||
|
assertTrue("Created a valid selector", selector != null);
|
||||||
|
MessageEvaluationContext context = new MessageEvaluationContext();
|
||||||
|
context.setMessageReference((org.apache.activemq.command.Message)message);
|
||||||
|
boolean value = selector.matches(context);
|
||||||
|
assertEquals("Selector for: " + text, matches, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String not(String selector) {
|
||||||
|
return "not(" + selector + ")";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue