001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.filter; 018 019import javax.jms.JMSException; 020import java.util.ArrayList; 021import java.util.List; 022 023/** 024 * A sequence of expressions, to be combined with OR or AND conjunctions. 025 * 026 */ 027public abstract class LogicExpression implements BooleanExpression { 028 029 protected final List<BooleanExpression> expressions = new ArrayList<>(2); 030 031 private LogicExpression(BooleanExpression lvalue, BooleanExpression rvalue) { 032 expressions.add(lvalue); 033 expressions.add(rvalue); 034 } 035 036 protected void addExpression(BooleanExpression expression) { 037 expressions.add(expression); 038 } 039 040 public BooleanExpression getLeft() { 041 if (expressions.size() == 2) { 042 return expressions.get(0); 043 } 044 throw new IllegalStateException("This expression is not binary: " + this); 045 } 046 047 public BooleanExpression getRight() { 048 if (expressions.size() == 2) { 049 return expressions.get(1); 050 } 051 throw new IllegalStateException("This expression is not binary: " + this); 052 } 053 054 /** 055 * Returns the symbol that represents this binary expression. For example, addition is 056 * represented by "+" 057 * 058 * @return 059 */ 060 public abstract String getExpressionSymbol(); 061 062 @Override 063 public String toString() { 064 if (expressions.size() == 2) { 065 return "( " + expressions.get(0) + " " + getExpressionSymbol() + " " + expressions.get(1) + " )"; 066 } 067 StringBuilder result = new StringBuilder("("); 068 int count = 0; 069 for (BooleanExpression expression : expressions) { 070 if (count++ > 0) { 071 result.append(" " + getExpressionSymbol() + " "); 072 } 073 result.append(expression.toString()); 074 } 075 result.append(")"); 076 return result.toString(); 077 } 078 079 public static BooleanExpression createOR(BooleanExpression lvalue, BooleanExpression rvalue) { 080 if (lvalue instanceof ORExpression) { 081 ORExpression orExpression = (ORExpression) lvalue; 082 orExpression.addExpression(rvalue); 083 return orExpression; 084 } else { 085 return new ORExpression(lvalue, rvalue); 086 } 087 } 088 089 public static BooleanExpression createAND(BooleanExpression lvalue, BooleanExpression rvalue) { 090 if (lvalue instanceof ANDExpression) { 091 ANDExpression orExpression = (ANDExpression) lvalue; 092 orExpression.addExpression(rvalue); 093 return orExpression; 094 } else { 095 return new ANDExpression(lvalue, rvalue); 096 } 097 } 098 099 @Override 100 public abstract Object evaluate(MessageEvaluationContext message) throws JMSException; 101 102 @Override 103 public abstract boolean matches(MessageEvaluationContext message) throws JMSException; 104 105 public static class ORExpression extends LogicExpression { 106 107 public ORExpression(BooleanExpression lvalue, BooleanExpression rvalue) { 108 super(lvalue, rvalue); 109 } 110 111 @Override 112 public Object evaluate(MessageEvaluationContext message) throws JMSException { 113 boolean someNulls = false; 114 for (BooleanExpression expression : expressions) { 115 Boolean lv = (Boolean)expression.evaluate(message); 116 if (lv != null && lv.booleanValue()) { 117 return Boolean.TRUE; 118 } 119 if (lv == null) { 120 someNulls = true; 121 } 122 } 123 if (someNulls) { 124 return null; 125 } 126 return Boolean.FALSE; 127 } 128 129 @Override 130 public boolean matches(MessageEvaluationContext message) throws JMSException { 131 for (BooleanExpression expression : expressions) { 132 boolean lv = expression.matches(message); 133 if (lv) { 134 return true; 135 } 136 } 137 return false; 138 } 139 140 @Override 141 public String getExpressionSymbol() { 142 return "OR"; 143 } 144 } 145 146 private static class ANDExpression extends LogicExpression { 147 148 public ANDExpression(BooleanExpression lvalue, BooleanExpression rvalue) { 149 super(lvalue, rvalue); 150 } 151 152 @Override 153 public Object evaluate(MessageEvaluationContext message) throws JMSException { 154 boolean someNulls = false; 155 for (BooleanExpression expression : expressions) { 156 Boolean lv = (Boolean)expression.evaluate(message); 157 if (lv != null && !lv.booleanValue()) { 158 return Boolean.FALSE; 159 } 160 if (lv == null) { 161 someNulls = true; 162 } 163 } 164 if (someNulls) { 165 return null; 166 } 167 return Boolean.TRUE; 168 } 169 170 @Override 171 public boolean matches(MessageEvaluationContext message) throws JMSException { 172 for (BooleanExpression expression : expressions) { 173 boolean lv = expression.matches(message); 174 if (!lv) { 175 return false; 176 } 177 } 178 return true; 179 } 180 181 @Override 182 public String getExpressionSymbol() { 183 return "AND"; 184 } 185 } 186}