package com.plexobject.rbac.eval.simple; import java.util.ArrayList; import java.util.Collection; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.validator.GenericValidator; public class Expression { private static final Pattern EXPRESSION_SPLIT_PATTERN = Pattern .compile("(\\s+and\\s+|\\s+or\\s+|\\s+\\&\\&\\s+|\\s\\|\\|\\s+|;|,)"); private static final Pattern TOKEN_SPLIT_PATTERN = Pattern .compile("(\\s+|')"); private final String name; private final Type type; private final Operator operator; private final String value; // time value must be in millisSince1970 or // HH:MM:ss public static Collection<Expression> parse(final String expression) { if (GenericValidator.isBlankOrNull(expression)) { throw new IllegalArgumentException("expression not specified"); } final String[] rawExprs = EXPRESSION_SPLIT_PATTERN.split(expression); Collection<Expression> exprs = new ArrayList<Expression>(); for (String rawExpr : rawExprs) { String[] tokens = TOKEN_SPLIT_PATTERN.split(rawExpr.trim()); if (tokens.length < 3) { throw new IllegalArgumentException("illegal expression in " + rawExpr + ", full " + expression); } String value = null; int start, end; if ((start = rawExpr.indexOf("'")) != -1 && (end = rawExpr.lastIndexOf("'")) != -1 && start < end) { value = rawExpr.substring(start + 1, end); } else if ((start = rawExpr.indexOf("\"")) != -1 && (end = rawExpr.lastIndexOf("\"")) != -1 && start < end) { value = rawExpr.substring(start + 1, end); } else { value = StringUtils.join(tokens, " ", 2, tokens.length) .replaceAll("\\s+", " "); } value = value.trim(); String name = tokens[0]; Type type = Type.isNumber(tokens[2]) ? Type.NUMBER : value .indexOf(":") != -1 ? Type.TIME : Type.STRING; Operator operator = Operator.bySymbol(tokens[1]); exprs.add(new Expression(name, type, operator, value)); } return exprs; } public Expression(String name, Type type, Operator operator, String value) { if (GenericValidator.isBlankOrNull(name)) { throw new IllegalArgumentException("name not specified"); } if (type == null) { throw new IllegalArgumentException("type not specified"); } if (operator == null) { throw new IllegalArgumentException("operator not specified"); } if (value == null) { throw new IllegalArgumentException("value not specified"); } this.name = name; this.type = type; this.operator = operator; this.value = value; } public String getName() { return name; } public Type getType() { return type; } public Operator getOperator() { return operator; } public String getValue() { return value; } public boolean evaluate(final String value) { return operator.matches(this.value, value, this.type); } /** * @see java.lang.Object#equals(Object) */ @Override public boolean equals(Object object) { if (!(object instanceof Expression)) { return false; } Expression rhs = (Expression) object; return new EqualsBuilder().append(this.name, rhs.name).append( this.type, rhs.type).append(this.operator, rhs.operator) .append(this.value, rhs.value).isEquals(); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return new HashCodeBuilder(786529047, 1924536713).append(this.name) .toHashCode(); } /** * @see java.lang.Object#toString() */ @Override public String toString() { return this.name + ":" + this.type + " " + this.operator + " " + this.value; } }