Back to index

lightning-sunbird  0.9+nobinonly
Public Types | Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes
JoinNode Class Reference

A node that joins to paths from the root node, and binds a variable from the left ancestor to a variable in the right ancestor. More...

#include <nsRuleNetwork.h>

Inheritance diagram for JoinNode:
Inheritance graph
[legend]
Collaboration diagram for JoinNode:
Collaboration graph
[legend]

List of all members.

Public Types

enum  Operator { eEquality }

Public Member Functions

 JoinNode (InnerNode *aLeftParent, PRInt32 aLeftVariable, InnerNode *aRightParent, PRInt32 aRightVariable, Operator aOperator)
virtual nsresult Propagate (const InstantiationSet &aInstantiations, void *aClosure)
 Propagate a set of instantiations "down" through the network.
virtual nsresult Constrain (InstantiationSet &aInstantiations, void *aClosure)
 This is called by a child node on its parent to allow the parent's constraints to apply to the set of instantiations.
virtual nsresult GetAncestorVariables (VariableSet &aVariables) const
 Retrieve the set of variables that are introduced by this node and any of its ancestors.
virtual PRBool HasAncestor (const ReteNode *aNode) const
 Determine if this node has another node as its direct ancestor.
nsresult AddChild (ReteNode *aNode)
 Add another node as a child of this node.
nsresult RemoveAllChildren ()
 Remove all the children of this node.

Protected Member Functions

nsresult Bind (InstantiationSet &aInstantiations, PRBool *aDidBind)

Static Protected Member Functions

static nsresult GetNumBound (InnerNode *aAncestor, const InstantiationSet &aInstantiations, PRInt32 *aBoundCount)

Protected Attributes

InnerNodemLeftParent
PRInt32 mLeftVariable
InnerNodemRightParent
PRInt32 mRightVariable
Operator mOperator
ReteNodeSet mKids

Detailed Description

A node that joins to paths from the root node, and binds a variable from the left ancestor to a variable in the right ancestor.

Definition at line 1011 of file nsRuleNetwork.h.


Member Enumeration Documentation

Enumerator:
eEquality 

Definition at line 1014 of file nsRuleNetwork.h.

{ eEquality };

Constructor & Destructor Documentation

JoinNode::JoinNode ( InnerNode aLeftParent,
PRInt32  aLeftVariable,
InnerNode aRightParent,
PRInt32  aRightVariable,
Operator  aOperator 
)

Definition at line 798 of file nsRuleNetwork.cpp.

    : mLeftParent(aLeftParent),
      mLeftVariable(aLeftVariable),
      mRightParent(aRightParent),
      mRightVariable(aRightVariable),
      mOperator(aOperator)
{
}

Member Function Documentation

nsresult InnerNode::AddChild ( ReteNode aNode) [inline, inherited]

Add another node as a child of this node.

Parameters:
aNodethe node to add.
Returns:
NS_OK if no errors occur.

Definition at line 973 of file nsRuleNetwork.h.

{ return mKids.Add(aNode); }

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult JoinNode::Bind ( InstantiationSet aInstantiations,
PRBool aDidBind 
) [protected]

Definition at line 887 of file nsRuleNetwork.cpp.

{
    // Try to use the instantiation set to bind the unbound join
    // variable. If successful, aDidBind <= PR_TRUE.
    nsresult rv;

    PRBool hasLeftAssignment = aInstantiations.HasAssignmentFor(mLeftVariable);
    PRBool hasRightAssignment = aInstantiations.HasAssignmentFor(mRightVariable);

    NS_ASSERTION(! (hasLeftAssignment && hasRightAssignment), "there is more than one assignment specified");
    if (hasLeftAssignment && hasRightAssignment)
        return NS_ERROR_UNEXPECTED;

    if (hasLeftAssignment || hasRightAssignment) {
        InstantiationSet::Iterator last = aInstantiations.Last();
        for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
            if (hasLeftAssignment) {
                // the left is bound
                Value leftValue;
                inst->mAssignments.GetAssignmentFor(mLeftVariable, &leftValue);
                rv = inst->AddAssignment(mRightVariable, leftValue);
            }
            else {
                // the right is bound
                Value rightValue;
                inst->mAssignments.GetAssignmentFor(mRightVariable, &rightValue);
                rv = inst->AddAssignment(mLeftVariable, rightValue);
            }

            if (NS_FAILED(rv)) return rv;
        }

        *aDidBind = PR_TRUE;
    }
    else {
        *aDidBind = PR_FALSE;
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult JoinNode::Constrain ( InstantiationSet aInstantiations,
void aClosure 
) [virtual]

This is called by a child node on its parent to allow the parent's constraints to apply to the set of instantiations.

A node must iterate through the set of instantiations, and for each instantiation, either 1) extend the instantiation by adding variable-to-value assignments and memory element support for those assignments, or 2) remove the instantiation because it is inconsistent.

The node must then pass the resulting set of instantiations up to its parent (by recursive call; we should make this iterative & interruptable at some point.)

Parameters:
aInstantiationsthe set of instantiations that must be constrained
aClosureapplication-specific information that needs to be passed through the network.
Returns:
NS_OK if no errors occurred

Implements InnerNode.

Definition at line 929 of file nsRuleNetwork.cpp.

{
    if (aInstantiations.Empty())
        return NS_OK;

    nsresult rv;
    PRBool didBind;

    rv = Bind(aInstantiations, &didBind);
    if (NS_FAILED(rv)) return rv;

    PRInt32 numLeftBound;
    rv = GetNumBound(mLeftParent, aInstantiations, &numLeftBound);
    if (NS_FAILED(rv)) return rv;

    PRInt32 numRightBound;
    rv = GetNumBound(mRightParent, aInstantiations, &numRightBound);
    if (NS_FAILED(rv)) return rv;

    InnerNode *first, *last;
    if (numLeftBound > numRightBound) {
        first = mLeftParent;
        last = mRightParent;
    }
    else {
        first = mRightParent;
        last = mLeftParent;
    }

    rv = first->Constrain(aInstantiations, aClosure);
    if (NS_FAILED(rv)) return rv;

    if (! didBind) {
        rv = Bind(aInstantiations, &didBind);
        if (NS_FAILED(rv)) return rv;

        NS_ASSERTION(didBind, "uh oh, still no assignment");
    }

    rv = last->Constrain(aInstantiations, aClosure);
    if (NS_FAILED(rv)) return rv;

    if (! didBind) {
        // sort throught the full cross product
        NS_NOTYETIMPLEMENTED("write me");
    }

    return NS_OK;
}

Here is the call graph for this function:

nsresult JoinNode::GetAncestorVariables ( VariableSet aVariables) const [virtual]

Retrieve the set of variables that are introduced by this node and any of its ancestors.

To correctly implement this method, a node must add any variables that it introduces to the variable set, and then recursively call GetAncestorVariables() on its parent (or parents).

Parameters:
aVariablesThe variable set to which the callee will add its variables, and its ancestors variables.
Returns:
NS_OK if no errors occur.

Implements InnerNode.

Definition at line 981 of file nsRuleNetwork.cpp.

{
    nsresult rv;

    rv = mLeftParent->GetAncestorVariables(aVariables);
    if (NS_FAILED(rv)) return rv;

    rv = mRightParent->GetAncestorVariables(aVariables);
    if (NS_FAILED(rv)) return rv;

    
    if (mLeftVariable) {
        rv = aVariables.Add(mLeftVariable);
        if (NS_FAILED(rv)) return rv;
    }

    if (mRightVariable) {
        rv = aVariables.Add(mRightVariable);
        if (NS_FAILED(rv)) return rv;
    }

    return NS_OK;
}

Here is the call graph for this function:

nsresult JoinNode::GetNumBound ( InnerNode aAncestor,
const InstantiationSet aInstantiations,
PRInt32 aBoundCount 
) [static, protected]

Definition at line 865 of file nsRuleNetwork.cpp.

{
    // Compute the number of variables for an ancestor that are bound
    // in the current instantiation set.
    nsresult rv;

    VariableSet vars;
    rv = aAncestor->GetAncestorVariables(vars);
    if (NS_FAILED(rv)) return rv;

    PRInt32 count = 0;
    for (PRInt32 i = vars.GetCount() - 1; i >= 0; --i) {
        if (aInstantiations.HasAssignmentFor(vars.GetVariableAt(i)))
            ++count;
    }

    *aBoundCount = count;
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool JoinNode::HasAncestor ( const ReteNode aNode) const [virtual]

Determine if this node has another node as its direct ancestor.

Parameters:
aNodethe node to look for.
Returns:
PR_TRUE if aNode is a direct ancestor of this node, PR_FALSE otherwise.

Implements InnerNode.

Definition at line 1007 of file nsRuleNetwork.cpp.

{
    if (aNode == this) {
        return PR_TRUE;
    }
    else if (mLeftParent->HasAncestor(aNode) || mRightParent->HasAncestor(aNode)) {
        return PR_TRUE;
    }
    else {
        return PR_FALSE;
    }
}

Here is the call graph for this function:

nsresult JoinNode::Propagate ( const InstantiationSet aInstantiations,
void aClosure 
) [virtual]

Propagate a set of instantiations "down" through the network.

Each instantiation is a partial set of variable-to-value assignments, along with the memory elements that support it.

The node must evaluate each instantiation, and either 1) extend it with additional assignments and memory-element support, or 2) remove it from the set because it is inconsistent with the constraints that this node applies.

The node must then pass the resulting instantiation set along to any of its children in the network. (In other words, the node must recursively call Propagate() on its children. We should fix this to make the algorithm interruptable.)

Parameters:
aInstantiationsthe set of instantiations to propagate down through the network.
aClosureany application-specific information that needs to be passed through the network.
Returns:
NS_OK if no errors occurred.

Implements ReteNode.

Definition at line 812 of file nsRuleNetwork.cpp.

{
    // the add will have been propagated down from one of the parent
    // nodes: either the left or the right. Test the other node for
    // matches.
    nsresult rv;

    PRBool hasLeftAssignment = aInstantiations.HasAssignmentFor(mLeftVariable);
    PRBool hasRightAssignment = aInstantiations.HasAssignmentFor(mRightVariable);

    NS_ASSERTION(hasLeftAssignment ^ hasRightAssignment, "there isn't exactly one assignment specified");
    if (! (hasLeftAssignment ^ hasRightAssignment))
        return NS_ERROR_UNEXPECTED;

    InstantiationSet instantiations = aInstantiations;
    InnerNode* test = hasLeftAssignment ? mRightParent : mLeftParent;

    {
        // extend the assignments
        InstantiationSet::Iterator last = instantiations.Last();
        for (InstantiationSet::Iterator inst = instantiations.First(); inst != last; ++inst) {
            if (hasLeftAssignment) {
                // the left is bound
                Value leftValue;
                inst->mAssignments.GetAssignmentFor(mLeftVariable, &leftValue);
                rv = inst->AddAssignment(mRightVariable, leftValue);
            }
            else {
                // the right is bound
                Value rightValue;
                inst->mAssignments.GetAssignmentFor(mRightVariable, &rightValue);
                rv = inst->AddAssignment(mLeftVariable, rightValue);
            }

            if (NS_FAILED(rv)) return rv;
        }
    }

    if (! instantiations.Empty()) {
        // propagate consistency checking back up the tree
        rv = test->Constrain(instantiations, aClosure);
        if (NS_FAILED(rv)) return rv;

        ReteNodeSet::Iterator last = mKids.Last();
        for (ReteNodeSet::Iterator kid = mKids.First(); kid != last; ++kid)
            kid->Propagate(instantiations, aClosure);
    }

    return NS_OK;
}

Here is the call graph for this function:

nsresult InnerNode::RemoveAllChildren ( ) [inline, inherited]

Remove all the children of this node.

Returns:
NS_OK if no errors occur.

Definition at line 979 of file nsRuleNetwork.h.

{ return mKids.Clear(); }

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

ReteNodeSet InnerNode::mKids [protected, inherited]

Definition at line 982 of file nsRuleNetwork.h.

Definition at line 1033 of file nsRuleNetwork.h.

Definition at line 1034 of file nsRuleNetwork.h.

Definition at line 1037 of file nsRuleNetwork.h.

Definition at line 1035 of file nsRuleNetwork.h.

Definition at line 1036 of file nsRuleNetwork.h.


The documentation for this class was generated from the following files: