Expression.java :  » Workflow-Engines » Bossa » com » bigbross » bossa » resource » Java Open Source

Java Open Source » Workflow Engines » Bossa 
Bossa » com » bigbross » bossa » resource » Expression.java
/*
 * Bossa Workflow System
 *
 * $Id: Expression.java,v 1.8 2004/01/29 21:24:37 gdvieira Exp $
 *
 * Copyright (C) 2003,2004 OpenBR Sistemas S/C Ltda.
 *
 * This file is part of Bossa.
 *
 * Bossa is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

package com.bigbross.bossa.resource;

import java.io.Serializable;
import java.util.StringTokenizer;

/**
 * A node of one binary tree representing a compiled resource expression. <p>
 * The set arithmetic operations are:
 * <ul>
 * <li> Union: <code>+</code>
 * <li> Intersection: <code>^</code>
 * <li> Exclusion: <code>-</code>
 * </ul>
 *
 * The operands are resource names. <br>
 * Whitespace characters are ignored. <br>
 * The expression is evaluated from left to right. <br>
 * Parenthesis may be used to group subexpressions. <p>
 *
 * The resource is linked from the <code>ResourceRegistry</code> at the
 * compilation time, and is created if needed. A <code>$</code> may be used to
 * delay the resource resolution to evaluation time, using a new
 * <code>ResourceRegistry</code>. <p>
 *
 * A resource expression example is: <code>sales - $request</code> than means
 * that only the users of the "sales" group minus the users that are in the
 * "request" group provided in the evaluation moment are in this role.
 *
 * @author <a href="http://www.bigbross.com">BigBross Team</a>
 * @see ResourceRegistry
 */
public abstract class Expression implements Container, Serializable {

    protected final static char OR  = '+';
    protected final static char SUB = '-';
    protected final static char AND = '^';
    protected final static char VAR = '$';
    protected final static char SPC = ' ';
    protected final static char LP  = '(';
    protected final static char RP  = ')';

    protected final static String DELIM = "" + OR + SUB + AND + VAR + SPC + LP + RP;

    /**
     * Compiles a resource expression. <p>
     *
     * @param registry a <code>ResourceRegistry</code> to link the resources
     *        in the expression.
     * @param expression the resource expression to be compiled.
     * @return a <code>Expression</code> representing the compiled resource
     *         expression.
     */
    public static Expression compile(ResourceRegistry registry, String expression) {
        StringTokenizer expr = new StringTokenizer(expression, DELIM, true);
        return compile(registry, expr, compile(registry, expr, null));
    }

    /**
     * Parses a resource expression building a binary tree. <p>
     *
     * @param registry a <code>ResourceRegistry</code> to link the resources
     *        in the expression.
     * @param expression the remaining resource expression to be compiled.
     * @param node a <code>Expression</code> value of the left node.
     * @return a <code>Expression</code> node of the compiled resource
     *         expression.
     */
    protected static Expression compile(ResourceRegistry registry, StringTokenizer expression, Expression node) {
        if (!expression.hasMoreTokens()) {
            return node;
        }

        String tok = expression.nextToken();

        while (tok.charAt(0) == SPC) {
            tok = expression.nextToken();
        }

        switch (tok.charAt(0)) {

        case OR: // Union node
            return compile(registry, expression, new Node(node, compile(registry, expression, node)) {

                    public boolean contains(ResourceRegistry registry, Resource resource) {
                        return left.contains(registry, resource) || right.contains(registry, resource);
                    }

                    public String toString() {
                        return toString(OR);
                    }
                });

        case AND: // Intersection node
            return compile(registry, expression, new Node(node, compile(registry, expression, node)) {

                    public boolean contains(ResourceRegistry registry, Resource resource) {
                        return left.contains(registry, resource) && right.contains(registry, resource);
                    }

                    public String toString() {
                        return toString(AND);
                    }
                });

        case SUB: // Subtraction node
            return compile(registry, expression, new Node(node, compile(registry, expression, node)) {

                    public boolean contains(ResourceRegistry registry, Resource resource) {
                        return !right.contains(registry, resource) && left.contains(registry, resource);
                    }

                    public String toString() {
                        return toString(SUB);
                    }
                });

        case LP: // Parenthesis node
            return compile(registry, expression, compile(registry, expression, node));

        case RP: // Parenthesis end
            return node;

        case VAR: // Resource weak reference
            return new LazyReference(registry, expression.nextToken());

        default: // Resource reference
            return new Reference(registry, tok);

        }

    }

    /**
     * Determines if a resource is contained in this. <p>
     *
     * @param resource the resource to be looked for.
     * @return <code>true</code> if the resource is found, <code>false</code> otherwise.
     */
    public boolean contains(Resource resource) {
        return contains(null, resource);
    }

    /**
     * Determines if a resource is contained in this. <p>
     *
     * @param registry a <code>ResourceRegistry</code> to resolve lazy referenced resource.
     * @param resource the resource to be looked for.
     * @return <code>true</code> if the resource is found, <code>false</code> otherwise.
     */
    public abstract boolean contains(ResourceRegistry registry, Resource resource);

}

abstract class Node extends Expression {

    protected Expression left;
    protected Expression right;

    protected Node(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    /**
     * Returns a string with the resource expression. <p>
     *
     * @return a string representation of this resource.
     */
    protected String toString(char op) {
        StringBuffer sb = new StringBuffer();

        if (left instanceof Node) {
            sb.append("(").append(left).append(")");
        } else {
            sb.append(left);
        }

        sb.append(op);

        if (right instanceof Node) {
            sb.append("(").append(right).append(")");
        } else {
            sb.append(right);
        }

        return sb.toString();
    }

}

class Reference extends Expression {

    Resource group;

    Reference(ResourceRegistry registry, String resource) {
        this.group = registry.getResource(resource);
        if (group == null) {
            this.group = registry.createResourceImpl(resource, false);
        }
    }

    public boolean contains(ResourceRegistry registry, Resource resource) {
        return group != null && group.contains(resource);
    }

    public String toString() {
        return String.valueOf(group);
    }

}

class LazyReference extends Expression {

    ResourceRegistry registry;
    String resourceId;

    LazyReference(ResourceRegistry registry, String resourceId) {
        this.registry = registry;
        this.resourceId = resourceId;
    }

    public boolean contains(ResourceRegistry context, Resource resource) {
        Resource group = (context == null) ? registry.getResource(resourceId) : context.getResource(resourceId);
        return group != null && group.contains(resource);
    }

    public String toString() {
        return VAR + resourceId;
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.