All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jsftemplating.el.PermissionChecker Maven / Gradle / Ivy

/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://jsftemplating.dev.java.net/cddl1.html or
 * jsftemplating/cddl1.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at jsftemplating/cddl1.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.jsftemplating.el;

import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import com.sun.jsftemplating.component.ComponentUtil;
import com.sun.jsftemplating.layout.descriptors.LayoutElement;


/**
 *  

This class evaluates a Boolean equation. The supported functions / * operators are:

* *
  • $<type>{<key>} -- To read a value according to * <type> using <key> (See: * {@link VariableResolver}). (null is * interpretted as false, non boolean values (besides the string * "false") are interpretted to mean true)
  • *
  • '(' and ')' can be used to override order of operation
  • *
  • '!' negate a boolean value
  • *
  • '|' logical OR
  • *
  • '&' logical AND
  • *
  • '=' String equals
  • *
  • '<' less than between 2 Integers
  • *
  • '>' greater than between 2 Integers
  • *
  • '%' modulus of 2 Integers
  • *
* * *

Operator Precedence (for infix notation) is:

* *
  • () -- Highest
  • *
  • !
  • *
  • %
  • *
  • &
  • *
  • |
  • *
  • < and >
  • *
  • =
  • *
* * @see VariableResolver * * @author Ken Paulsen ([email protected]) */ public class PermissionChecker { /** * This is the constructor method that is required to create this object. */ public PermissionChecker(LayoutElement desc, UIComponent component, String infixStr) { if (infixStr == null) { infixStr = "false"; } setLayoutElement(desc); setUIComponent(component); setInfix(stripWhiteSpace(infixStr)); } /** *

This method sets the LayoutElement that is associated with the 'if' * check being evaluated. This is not normally needed, it is only needed * if the 'if' check contains an expression which requires a * LayoutElement to be properly evaluated.

*/ protected void setUIComponent(UIComponent component) { _component = component; } /** *

Retreives the LayoutElement associated with this PermissionChecker * (only needed in cases where a expression requires a LayoutElement for * evaluation).

*/ public UIComponent getUIComponent() { return _component; } /** *

This method sets the LayoutElement that is associated with the 'if' * check being evaluated. This is not normally needed, it is only needed * if the 'if' check contains an expression which requires a * LayoutElement to be properly evaluated.

*/ protected void setLayoutElement(LayoutElement desc) { _desc = desc; } /** *

Retreives the LayoutElement associated with this PermissionChecker * (only needed in cases where a expression requires a LayoutElement for * evaluation).

*/ public LayoutElement getLayoutElement() { return _desc; } /** *

This method returns the precedence of the given operator. This * only applies to infix notation (of course) and is needed to * correctly order the operators when converting to postfix.

* *
  • ! (not) has the highest precedence
  • *
  • % (modulus)
  • *
  • & (and)
  • *
  • | (or)
  • *
  • < (less than) and > (greater than)
  • *
  • = (equals)
  • *
* *

Of course '(' and ')' can be used to override the order of * operations in infix notation.

* * @param op The operator to evaluate. * * @return A number that can be used to compare its precedence. */ private static int getPrecedence(char op) { switch (op) { case LEFT_PAREN: return 1; case RIGHT_PAREN: return 999; case EQUALS_OPERATOR: return 2; case LESS_THAN_OPERATOR: case MORE_THAN_OPERATOR: return 4; case OR_OPERATOR: return 8; case AND_OPERATOR: return 16; case MODULUS_OPERATOR: case DIVIDE_OPERATOR: return 32; case NOT_OPERATOR: return 64; } return 1; } /** *

This method replaces all "true" / "false" strings w/ 't'/'f'. It * converts the String into a char[]. It replaces all user defined * functions w/ 'F' and places a Function in a list per the registered * user-defined function. All other strings are converted to an 'F' * and a StringFunction is added to the function list.

*/ protected char[] preProcessString(String source) { char[] arr = source.toCharArray(); int sourceLen = arr.length; int destLen = 0; // Loop through the String, char by char for (int idx = 0; idx < sourceLen; idx++) { switch (arr[idx]) { case POST_TRUE: case POST_TRUE_CAP: if (((idx + TRUE.length()) <= sourceLen) && TRUE.equalsIgnoreCase( new String(arr, idx, TRUE.length()))) { arr[destLen++] = POST_TRUE; idx += TRUE.length() - 1; } else { idx = storeFunction(arr, idx); arr[destLen++] = FUNCTION_MARKER; } break; case POST_FALSE: case POST_FALSE_CAP: if (((idx + FALSE.length()) <= sourceLen) && FALSE.equalsIgnoreCase( new String(arr, idx, FALSE.length()))) { arr[destLen++] = POST_FALSE; idx += FALSE.length() - 1; } else { idx = storeFunction(arr, idx); arr[destLen++] = FUNCTION_MARKER; } break; case OR_OPERATOR: case EQUALS_OPERATOR: case LESS_THAN_OPERATOR: case MORE_THAN_OPERATOR: case MODULUS_OPERATOR: case DIVIDE_OPERATOR: case AND_OPERATOR: case NOT_OPERATOR: case LEFT_PAREN: case RIGHT_PAREN: arr[destLen++] = arr[idx]; break; default: idx = storeFunction(arr, idx); arr[destLen++] = FUNCTION_MARKER; } } char[] dest = new char[destLen]; for (int idx = 0; idx < destLen; idx++) { dest[idx] = arr[idx]; } return dest; } /** *

This method looks at the given char array starting at index and * continues until an operator (or end of String) is encountered. It * then uses this string to lookup a registered function (if any), it * stores that function (with parameters)... or if the function is * not found, it registers a "String function" (which always returns * true).

*/ protected int storeFunction(char[] arr, int idx) { // Find string... int start = idx; int len = arr.length; while ((idx < len) && !isOperator(arr[idx])) { idx++; } // Create String... String str = new String(arr, start, idx - start); // Check to see if it is a registered function... Function function = getFunction(str); if (function != null) { // Find the left paren... int left = idx; if ((left >= len) || (arr[left] != LEFT_PAREN)) { throw new RuntimeException("Function '" + str + "' is expected to have a '" + LEFT_PAREN + "' immediately following it. Equation: '" + new String(arr) + "'."); } List arguments = new ArrayList(); // Find the right Paren... while ((++idx < len) && (arr[idx] != RIGHT_PAREN)) { if (arr[idx] == ARGUMENT_SEPARATOR) { left++; arguments.add(new String(arr, left, idx - left)); left = idx; } } // Make sure we don't have () left++; if (idx > left) { arguments.add(new String(arr, left, idx - left)); } // Set the arguments... function.setArguments(arguments); } else { // Not a registered function... idx--; // In this case, there are no ()'s to consume, backup 1 /* if ((str.charAt(0) == FUNCTION_MARKER) && (str.length() == 1) && !_tmpFunctionStack.empty()) { // We have a function added during the subtitute() phase function = (Function) _tmpFunctionStack.pop(); } else { */ // Create a StringFunction function = new StringFunction(str); /* } */ } // Add the function to the function list _functionList.add(function); // Return the number of characters that we consumed... return idx; } /** *

This returns a Map<String, Class> which * represent user-registered functions.

*/ private static Map getFunctions(FacesContext ctx) { Map funcs = null; if (ctx == null) { ctx = FacesContext.getCurrentInstance(); } if (ctx != null) { Map appMap = ctx.getExternalContext().getApplicationMap(); funcs = (Map) appMap.get(PERMISSION_FUNCTIONS); if (funcs == null) { // Perhaps a SoftReference would be a good idea here? funcs = new HashMap(); } } else { // Not JSF env, create every time... funcs = new HashMap(); } return funcs; } /** *

This sets a Map<String, Class> which * represent user-registered functions.

*/ private static void setFunctions(FacesContext ctx, Map map) { if (ctx == null) { ctx = FacesContext.getCurrentInstance(); } if (ctx != null) { // Only set if we're in a JSF env ctx.getExternalContext().getApplicationMap(). put(PERMISSION_FUNCTIONS, map); } } /** *

This method is a factory method for constructing a new function * based on the function name passed in. The function must be * registered prior to invoking this method.

*/ protected static Function getFunction(String functionName) { // Get the Function class Class functionClass = getFunctions(null).get(functionName); if (functionClass == null) { return null; } // Create a new instance Function function = null; try { function = (Function) functionClass.newInstance(); } catch (Exception ex) { throw new RuntimeException("Unable to instantiate '" + functionClass.getName() + "' for '" + functionName + "'", ex); } // Return the instance return function; } /** *

This method allows arbitrary functions to be registered. Function * names should only contain letters or numbers, other characters or * whitespace may cause problems. No checking is done to ensure this, * however.

* *

Functions will be expressed in an equation as follows:

* *
  • function_name(param1,param2)
* *

Function parameters also should only contain alpha-numeric * characters.

* *

Functions must implement PermissionChecker.Function interface

*/ public static void registerFunction(String functionName, Class function) { // Get a copy of the existing f()'s Map newFuncs = new HashMap(getFunctions(null)); if (function == null) { // Remove it... newFuncs.remove(functionName); } else { if (!Function.class.isAssignableFrom(function)) { throw new RuntimeException("'" + function.getName() + "' must implement '" + Function.class.getName() + "'"); } // Add it... newFuncs.put(functionName, function); } // Save new copy of function Map setFunctions(null, newFuncs); } /** *

This method returns true if the given character is a valid * operator.

*/ public static boolean isOperator(char ch) { switch (ch) { case LEFT_PAREN: case RIGHT_PAREN: case EQUALS_OPERATOR: case LESS_THAN_OPERATOR: case MORE_THAN_OPERATOR: case MODULUS_OPERATOR: case DIVIDE_OPERATOR: case OR_OPERATOR: case AND_OPERATOR: case NOT_OPERATOR: // case AT_OPERATOR: // case POUND_OPERATOR: // case DOLLAR_OPERATOR: // case UP_OPERATOR: // case STAR_OPERATOR: // case TILDA_OPERATOR: // case ARGUMENT_SEPARATOR: return true; } return false; } /** *

This method calculates the postfix representation of the infix * equation passed in. It returns the postfix equation as a * char[].

* * @param infixStr The infix representation of the equation. * * @return postfix representation of the equation as a char[] (the f()'s * are removed and stored in _functionList). */ protected char [] generatePostfix(String infixStr) { // Reset the _functionList _functionList = new ArrayList(); // Convert string to our parsable format char[] result = preProcessString(infixStr); //System.out.println("DEBUG: Initial String: '"+infixStr+"'"); //System.out.println("DEBUG: After Pre-process: '"+new String(result)+"'"); int resultLen = result.length; int postIdx = 0; int precedence = 0; Stack opStack = new Stack(); // Put f()'s directly into result, push operators into right order for (int idx = 0; idx < resultLen; idx++) { switch(result[idx]) { case FUNCTION_MARKER: case POST_TRUE: case POST_FALSE: result[postIdx++] = result[idx]; break; case LEFT_PAREN: opStack.push(new Character(LEFT_PAREN)); break; case RIGHT_PAREN: while (!opStack.empty() && (((Character) opStack.peek()).charValue() != LEFT_PAREN)) { result[postIdx++] = ((Character) opStack.pop()).charValue(); } if (!opStack.empty()) { // Throw away the LEFT_PAREN that should still be there opStack.pop(); } break; default: // clear stuff precedence = getPrecedence(result[idx]); while (!opStack.empty() && (getPrecedence(((Character) opStack.peek()). charValue()) >= precedence)) { result[postIdx++] = ((Character) opStack.pop()).charValue(); } /* Put it on the stack */ opStack.push(new Character(result[idx])); break; } } // empty the rest of the stack to the result while (!opStack.empty()) { result[postIdx++] = ((Character) opStack.pop()).charValue(); } // Copy the result to the postfixStr char[] postfixStr = new char[postIdx]; for (int idx = 0; idx < postIdx; idx++) { postfixStr[idx] = result[idx]; } //System.out.println("DEBUG: Postfix String: '"+new String(postfixStr)+"'"); return postfixStr; } /** *

This method is invoked to determine if the equation evaluates to * true or false.

*/ public boolean hasPermission() { char[] postfixArr = getPostfixArr(); int len = postfixArr.length; Stack result = new Stack(); result.push(FALSE_BOOLEAN_FUNCTION); // Default to false boolean val1, val2; Iterator it = _functionList.iterator(); // Iterate through the postfix array for (int idx = 0; idx < len; idx++) { switch (postfixArr[idx]) { case POST_TRUE: result.push(TRUE_BOOLEAN_FUNCTION); break; case POST_FALSE: result.push(FALSE_BOOLEAN_FUNCTION); break; case FUNCTION_MARKER: if (!it.hasNext()) { throw new RuntimeException("Unable to evaluate: '" + toString() + "' -- found function marker " + "w/o cooresponding function!"); } result.push(it.next()); break; case EQUALS_OPERATOR: try { // Allow reg expression matching String matchStr = result.pop().toString(); val1 = result.pop().toString().matches(matchStr); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } result.push(val1 ? TRUE_BOOLEAN_FUNCTION : FALSE_BOOLEAN_FUNCTION); break; case LESS_THAN_OPERATOR: try { // The stack reverses the order, so check greater than val1 = Integer.parseInt(result.pop().toString()) > Integer.parseInt(result.pop().toString()); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } result.push(val1 ? TRUE_BOOLEAN_FUNCTION : FALSE_BOOLEAN_FUNCTION); break; case MORE_THAN_OPERATOR: try { // The stack reverses the order, so check less than val1 = Integer.parseInt(result.pop().toString()) < Integer.parseInt(result.pop().toString()); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } result.push(val1 ? TRUE_BOOLEAN_FUNCTION : FALSE_BOOLEAN_FUNCTION); break; case MODULUS_OPERATOR: try { // The stack reverses the order... int modNumber = Integer.parseInt(result.pop().toString()); int num = Integer.parseInt(result.pop().toString()); result.push(new StringFunction("" + (num % modNumber))); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } break; case DIVIDE_OPERATOR: try { // The stack reverses the order... int divNumber = Integer.parseInt(result.pop().toString()); int num = Integer.parseInt(result.pop().toString()); result.push(new StringFunction("" + (num / divNumber))); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } break; case OR_OPERATOR: try { val1 = ((Function) result.pop()).evaluate(); val2 = ((Function) result.pop()).evaluate(); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } result.push((val1 || val2) ? TRUE_BOOLEAN_FUNCTION : FALSE_BOOLEAN_FUNCTION); break; case AND_OPERATOR: try { val1 = ((Function) result.pop()).evaluate(); val2 = ((Function) result.pop()).evaluate(); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } result.push((val1 && val2) ? TRUE_BOOLEAN_FUNCTION : FALSE_BOOLEAN_FUNCTION); break; case NOT_OPERATOR: try { val1 = ((Function) result.pop()).evaluate(); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } result.push((!val1) ? TRUE_BOOLEAN_FUNCTION : FALSE_BOOLEAN_FUNCTION); break; } } // Return the only element on the stack (hopefully) try { val1 = ((Function) result.pop()).evaluate(); } catch (EmptyStackException ex) { throw new RuntimeException("Unable to evaluate: '" + toString() + "'.", ex); } if (!result.empty()) { result.pop(); // We added a false that wasn't needed if (!result.empty()) { throw new RuntimeException("Unable to evaluate: '" + toString() + "' -- values left on the stack."); } } return val1; } /** *

This method returns the infix representation of the equation, in * other words: the original String passed in.

*/ public String getInfix() { return _infixStr; } /** *

This method sets the equation and forces a re-evaluation of the * equation. It returns the postfix representation of the * equation.

* * @param equation The infix equation to use. * */ public void setInfix(String equation) { _infixStr = equation; setPostfixArr(generatePostfix(equation)); } /** *

Getter for the post fix array. If it is currently null, an empty * char[] array will be returned.

*/ protected char [] getPostfixArr() { if (_postfixArr == null) { _postfixArr = new char[] {' '}; } return _postfixArr; } /** *

Setter for the postfix array of chars.

*/ protected void setPostfixArr(char[] postfix) { _postfixArr = postfix; } /** *

This method provides access to a String representation * of the postfix equation held by this Object.

*/ public String getPostfix() { if (getPostfixArr() == null) { return ""; } return new String(getPostfixArr()); } /** *

Displays the infix and postfix version of the equation.

*/ public String toString() { return _infixStr + " = " + toString(getPostfixArr()); } /** *

This toString(...) method generates just the postfix * representation of the equation. The postfix notation is stored as * a char[] and it has the functions removed from the char[]. This * method iterates through the char[] and generates a String with the * functions put back into the equation.

* * @param post The char[] representation of the postfix equation. */ private String toString(char[] post) { int len = post.length; StringBuffer result = new StringBuffer(""); Iterator it = _functionList.iterator(); for (int idx = 0; idx < len; idx++) { switch (post[idx]) { case POST_TRUE: result.append(TRUE); break; case POST_FALSE: result.append(FALSE); break; case FUNCTION_MARKER: result.append((it.next()).toString()); break; default: result.append(post[idx]); } } return result.toString(); } /** *

This method removes all whitespace from the given String.

*/ public static String stripWhiteSpace(String input) { char[] arr = input.toCharArray(); int len = arr.length; int destLen = 0; // Loop through the array skipping whitespace for (int idx = 0; idx < len; idx++) { if (Character.isWhitespace(arr[idx])) { continue; } arr[destLen++] = arr[idx]; } // Return the result return new String(arr, 0, destLen); } /** *

This class must be implemented by all user defined Functions.

* *

In addition to these methods, a toString() should be implemented * that reconstructs the original format of the function (i.e. * function_name(arg1,arg2...)).

*/ public static interface Function { /** *

This method returns the List of arguments.

*/ public List getArguments(); /** *

This method is invoked be the PermissionChecker to set the * arguments.

*/ public void setArguments(List args); /** *

This method is invoked by the PermissionCheck to evaluate the * function to true or false.

*/ public boolean evaluate(); } /** *

StringFunction implements Function and * serves as the default function. This function is special in that * it is NEVER registered and is the only function that SHOULD NOT be * followed by ()'s. This function will process embedded expressions * and evaulate to false if the entire string evaulates to null. * Otherwise it will return true. This Function ignores * all arguments (arguments only apply if it is registered, which * shouldn't be the case anyway).

*/ protected class StringFunction implements PermissionChecker.Function { /** * Constructor. * * @param value The expression to evaluate. */ public StringFunction(String value) { _value = value; } /** * Not used. */ public List getArguments() { return null; } /** * Not used. */ public void setArguments(List args) { } /** *

Determine if the value of the Function is * true or false.

*/ public boolean evaluate() { Object obj = getEvaluatedValue(); if (obj == null) { return false; } obj = obj.toString(); if (obj.equals("")) { return false; } if (((String) obj).equalsIgnoreCase("false")) { return false; } return true; } /** *

This methis uses the {@link VariableResolver} to evaluate the * String and returns the result.

*/ public Object getEvaluatedValue() { FacesContext ctx = FacesContext.getCurrentInstance(); return ComponentUtil.getInstance(ctx).resolveValue( ctx, getLayoutElement(), getUIComponent(), _value); } /** *

This implementation of toString() returns the * evaluated value, except when the value is (null) * in which case it returns the empty string ("").

*/ public String toString() { Object obj = getEvaluatedValue(); if (obj == null) { return ""; } return obj.toString(); } private String _value; } /** *

BooleanFunction is either true or * false. It is used internally by * PermissionChecker and is not needed outside * PermissionChecker since the Strings "true" or "false" * used in an equation are sufficient.

*/ protected static class BooleanFunction implements PermissionChecker.Function { /** *

Constructor (defaults to false).

*/ public BooleanFunction() { } /** *

Constructor.

*/ public BooleanFunction(boolean value) { _value = value; } /** *

Not used.

*/ public List getArguments() { return null; } /** *

Not used.

*/ public void setArguments(List args) { } /** *

Return the value of the Function; * true or false.

*/ public boolean evaluate() { return _value; } /** *

This implementation prints the String "true" or * "false" based on the stored value.

*/ public String toString() { return _value ? "true" : "false"; } private boolean _value = false; } /** *

This is here to provide some test cases. It only tests the * conversion to postfix notation.

*/ public static void main(String[] args) { PermissionChecker checker; if (args.length > 0) { for (int count = 0; count < args.length; count++) { checker = new PermissionChecker(null, null, args[count]); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); } } else { boolean success = true; checker = new PermissionChecker(null, null, "false|false"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("false|false = falsefalse|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "true|false = truefalse|"); success = false; } if (checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "true |false"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("true|false = truefalse|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "true|false = truefalse|"); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "true&(false|true)"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("true&(false|true) = truefalsetrue|&")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "true&(false|true) = truefalsetrue|&"); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "true&false|true"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("true&false|true = truefalse&true|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "true&false|true = truefalse&true|"); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "true&true|false&true"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("true&true|false&true = truetrue&falsetrue&|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "true&true|false&true = truetrue&falsetrue&|"); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "!true|false&!(false|true)"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("!true|false&!(false|true) = true!falsefalsetrue|!&|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "!true|false&!(false|true) = true!falsefalsetrue|!&|"); success = false; } if (checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "!(!(true&!true)|!(false|false))|(true|false)&true"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("!(!(true&!true)|!(false|false))|(true|false)&true = truetrue!&!falsefalse|!|!truefalse|true&|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "!(!(true&!true)|!(false|false))|(true|false)&true = truetrue!&!falsefalse|!|!truefalse|true&|"); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } // Test '=' checker = new PermissionChecker(null, null, "false =false"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("false=false = falsefalse=")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "false=false = falsefalse="); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, " test= me "); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("test=me = testme=")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "test=me = testme="); success = false; } if (checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, " this should work=thisshouldwork"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("thisshouldwork=thisshouldwork = thisshouldworkthisshouldwork=")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "thisshouldwork=thisshouldwork = thisshouldworkthisshouldwork="); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "false|ab=true"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("false|ab=true = falseab|true=")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "false|ab=true = falseab|true="); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "false|(ab=true)"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("false|(ab=true) = falseabtrue=|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "false|ab=true = falseab|true="); success = false; } if (checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "false|(ab=ab)"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("false|(ab=ab) = falseabab=|")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "false|ab=true = falseab|true="); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "!"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("! = !")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "! = !"); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, ""); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals(" = ")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + " = "); success = false; } if (checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "!$escape{}"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("!$escape{} = !")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + "! = !"); success = false; } if (!checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } checker = new PermissionChecker(null, null, "$escape{}"); System.out.println("Output:\n" + checker.toString() + " (" + checker.hasPermission() + ")"); if (!checker.toString().equals("$escape{} = ")) { System.out.println("\tFAILED!"); System.out.println("Should have been:\n" + " = "); success = false; } if (checker.hasPermission()) { System.out.println("\tFAILED!"); System.out.println("hasPermission(" + checker.toString(checker.getPostfixArr()) + ") returned the wrong result!"); success = false; } if (success) { System.out.println("\n\tALL TESTS PASSED!"); } else { System.out.println("\n\tNOT ALL TESTS PASSED!"); } } } /** *

This variable represents a "false" BooleanFunction.

*/ public static final BooleanFunction FALSE_BOOLEAN_FUNCTION = new BooleanFunction(false); /** *

This variable represents a "true" BooleanFunction.

*/ public static final BooleanFunction TRUE_BOOLEAN_FUNCTION = new BooleanFunction(true); protected static final char POST_TRUE = 't'; protected static final char POST_FALSE = 'f'; protected static final char POST_TRUE_CAP = 'T'; protected static final char POST_FALSE_CAP = 'F'; public static final String TRUE = "true"; public static final String FALSE = "false"; // Function representation in postfix String public static final char FUNCTION_MARKER = 'F'; // Operator constants public static final char LEFT_PAREN = '('; public static final char RIGHT_PAREN = ')'; public static final char EQUALS_OPERATOR = '='; public static final char OR_OPERATOR = '|'; public static final char AND_OPERATOR = '&'; public static final char NOT_OPERATOR = '!'; public static final char LESS_THAN_OPERATOR = '<'; public static final char MORE_THAN_OPERATOR = '>'; public static final char MODULUS_OPERATOR = '%'; public static final char DIVIDE_OPERATOR = '/'; // The COMMA separates function arguments... not really an operator public static final char ARGUMENT_SEPARATOR = ','; // Reserved operators, although not currently used... /* * These may be added eventually * * public static final char AT_OPERATOR = '@'; * public static final char POUND_OPERATOR = '#'; * public static final char DOLLAR_OPERATOR = '$'; * public static final char UP_OPERATOR = '^'; * public static final char STAR_OPERATOR = '*'; * public static final char TILDA_OPERATOR = '~'; */ private static final String PERMISSION_FUNCTIONS = "__jsft_permFuncs"; /** *

This holds the infix equation.

*/ private String _infixStr = null; /** *

This holds the postfix equation.

*/ private char[] _postfixArr = null; /** *

This List holds the actual Function objects that correspond to the * 'F' markers in the postfix string.

*/ private List _functionList = null; /** *

This List of functions maintains variableSubstitution Functions * which happen out-of-order. They will be pulled from this list as * placed into the actual _functionList when the are encountered * during the preProcessing.

*/ // private Stack _tmpFunctionStack = null; private LayoutElement _desc = null; private UIComponent _component = null; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy