001: /**
002: *
003: */package prefuse.util;
004:
005: import prefuse.data.Tuple;
006: import prefuse.data.expression.Expression;
007: import prefuse.data.expression.IfExpression;
008: import prefuse.data.expression.ObjectLiteral;
009: import prefuse.data.expression.Predicate;
010:
011: /**
012: * A chain of Predicates and associated values, maintain a large
013: * if-statement structure for looking up values based on a Predicate
014: * condition.
015: * @author <a href="http://jheer.org">jeffrey heer</a>
016: */
017: public class PredicateChain {
018:
019: private Expression m_head = new ObjectLiteral(null);
020: private IfExpression m_tail = null;
021:
022: /**
023: * Return the backing predicate chain as an Expression instance.
024: * @return the predicate chain, either an IfExpression or
025: * the single terminal default Expression instance.
026: */
027: public Expression getExpression() {
028: return m_head;
029: }
030:
031: /**
032: * Evaluate the predicate chain for the given Tuple.
033: * @param t the Tuple
034: * @return the object associated with the first Predicate
035: * that successfully matches the Tuple.
036: */
037: public Object get(Tuple t) {
038: return m_head.get(t);
039: }
040:
041: /**
042: * Add a new rule to the end of the chain, associating a Predicate
043: * condition with an Object value.
044: * @param p the Predicate condition
045: * @param val the associated Object value
046: */
047: public void add(Predicate p, Object val) {
048: if (m_tail == null) {
049: m_tail = new IfExpression(p, new ObjectLiteral(val), m_head);
050: m_head = m_tail;
051: } else {
052: IfExpression ie = new IfExpression(p,
053: new ObjectLiteral(val), m_tail.getElseExpression());
054: m_tail.setElseExpression(ie);
055: m_tail = ie;
056: }
057: }
058:
059: /**
060: * Remove rules using the given predicate from this predicate chain.
061: * This method will not remove rules in which this predicate is used
062: * within a composite of clauses, such as an AND or OR. It only removes
063: * rules using this predicate as the top-level trigger.
064: * @param p the predicate to remove from the chain
065: * @return true if a rule was successfully removed, false otherwise
066: */
067: public boolean remove(Predicate p) {
068: if (p == null)
069: return false;
070:
071: IfExpression prev = null;
072: Expression expr = m_head;
073: while (expr instanceof IfExpression) {
074: IfExpression ifex = (IfExpression) expr;
075: Predicate test = (Predicate) ifex.getTestPredicate();
076: if (p.equals(test)) {
077: Expression elseex = ifex.getElseExpression();
078: ifex.setElseExpression(new ObjectLiteral(null));
079: if (prev != null) {
080: prev.setElseExpression(elseex);
081: if (ifex == m_tail)
082: m_tail = prev;
083: } else {
084: m_head = elseex;
085: if (ifex == m_tail)
086: m_tail = null;
087: }
088: return true;
089: } else {
090: prev = ifex;
091: expr = ifex.getElseExpression();
092: }
093: }
094: return false;
095: }
096:
097: /**
098: * Remove all rules from the predicate chain.
099: */
100: public void clear() {
101: m_head = new ObjectLiteral(null);
102: m_tail = null;
103: }
104:
105: } // end of class PredicateChain
|