package org.ff4j.strategy.el; /* * #%L * ff4j-core * %% * Copyright (C) 2013 Ff4J * %% * Licensed 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. * #L% */ import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Storage of an node in expression tree. * * @author Cedrick Lunven (@clunven) */ public class ExpressionNode { /** Operator pour l'expression. */ private ExpressionOperator operator; /** If value is not null and operator is null will be a sheet. */ private String value; /** La liste des sous nodes. */ private final List<ExpressionNode> subNodes = new ArrayList<ExpressionNode>(); /** * Constructor for sheet of tree (no operator). * * @param sheetValue * string expression for sheet, should be feature id */ public ExpressionNode(String sheetValue) { this.value = sheetValue; } /** * Build only with Operator (no sheet, no subnodes) * * @param ops * target Operator. */ public ExpressionNode(ExpressionOperator ops) { this.operator = ops; } /** * Evalue the whole expression tree. * * @return constante will be substitue. */ public boolean evalue(Map<String, Boolean> stateMap) { if (value != null && !value.isEmpty()) { return evaluateValue(stateMap); } else if (ExpressionOperator.NOT.equals(operator)) { return evaluateOperatorNot(stateMap); } else if (ExpressionOperator.AND.equals(operator)) { return evaluateOperatorAnd(stateMap); } else { // Only left return evaluateOperatorOr(stateMap); } } /** * Evaluate map for substitutions. * * @param stateMap * map with expression states * @return state of target key is present */ private boolean evaluateValue(Map<String, Boolean> stateMap) { if (stateMap.containsKey(value)) { return stateMap.get(value); } return false; } /** * Evaluate operator not. * * @param stateMap * map of states * @return state of target key is present */ private boolean evaluateOperatorNot(Map<String, Boolean> stateMap) { return !subNodes.get(0).evalue(stateMap); } /** * Evaluate operator AND. * * @param stateMap * map of states * @return state of target key is present */ private boolean evaluateOperatorAnd(Map<String, Boolean> stateMap) { boolean status = true; int idx = 0; while (status && idx < subNodes.size()) { status = subNodes.get(idx).evalue(stateMap); idx++; } return status; } /** * Evaluate operator OR. * * @param stateMap * map of states * @return state of target key is present */ private boolean evaluateOperatorOr(Map<String, Boolean> stateMap) { boolean status; int idx = 0; // No ternaire expression, simplier status = false; while (!status && idx < subNodes.size()) { status = subNodes.get(idx).evalue(stateMap); idx++; } return status; } /** {@inheritDoc} */ @Override public String toString() { if (value != null && !value.isEmpty()) { return value; } else { StringBuilder strBuilder = new StringBuilder(""); boolean first; if (ExpressionOperator.NOT.equals(operator)) { strBuilder.append("!"); } first = true; // Display subNodes embedded with parenthesis for (ExpressionNode subnode : subNodes) { if (!first) { strBuilder.append(" " + operator + " "); } if (subnode.getValue() == null || subnode.getValue().isEmpty()) { strBuilder.append("(" + subnode.toString() + ")"); } else { strBuilder.append(subnode.toString()); } first = false; } return strBuilder.toString(); } } /** * Getter accessor for attribute 'operator'. * * @return current value of 'operator' */ public ExpressionOperator getOperator() { return operator; } /** * Setter accessor for attribute 'operator'. * * @param operator * new value for 'operator ' */ public void setOperator(ExpressionOperator operator) { this.operator = operator; } /** * Getter accessor for attribute 'value'. * * @return current value of 'value' */ public String getValue() { return value; } /** * Setter accessor for attribute 'value'. * * @param value * new value for 'value ' */ public void setValue(String value) { this.value = value; } /** * Getter accessor for attribute 'subNodes'. * * @return current value of 'subNodes' */ public List<ExpressionNode> getSubNodes() { return subNodes; } }