/*
(c) Copyright 2008, 2009 Hewlett-Packard Development Company, LP
All rights reserved.
$Id$
*/
/*
(c) Copyright 2008 Hewlett-Packard Development Company, LP
All rights reserved.
$Id$
*/
package com.hp.jena.rules.retelike.impl;
import java.util.ArrayList;
import java.util.List;
import com.hp.jena.graph.Node;
import com.hp.jena.graph.NodeFactory;
import com.hp.jena.rules.retelike.impl.scratch.Functor;
/**
A NodeTerm is a term representing a node. It supports the <i>subst</i>
operation which replaces variables by their bound value.
@author kers
*/
public abstract class NodeTerm
{
protected final Node node;
public NodeTerm( Node node )
{ this.node = node; }
public Node getNode()
{ return node; }
/**
Answer the node resulting from binding any variables in
this NodeTerm with their values from <i>b</i>.
* @param c TODO
*/
public abstract Node subst( ExecContext c, Bindings<Node, Node> b );
/**
Answer true if this NodeTerm can bind to <i>n</i>, possibly
updating the bindings <i>b</i>.
*/
public abstract boolean bind( Node n, Bindings<Node, Node> b );
/**
Answer true if this NodeTerm is a plain variable.
*/
public abstract boolean isVariable();
@Override public int hashCode()
{ return node.hashCode(); }
@Override public boolean equals( Object other )
{ return other instanceof NodeTerm && node.equals( ((NodeTerm) other).node ); }
public static class NodeTermFunctor extends NodeTerm
{
protected final List<NodeTerm> terms;
@SuppressWarnings("unchecked") public NodeTermFunctor( Node node )
{
super( node );
this.terms = new ArrayList<NodeTerm>();
for (Node n: (List<Node>) node.getLiteralValue())
terms.add( create( n ) );
}
@SuppressWarnings("unchecked") @Override public boolean bind( Node n, Bindings<Node, Node> b )
{
return
n instanceof Functor
&& bind( (List<Node>) n.getLiteralValue(), b );
}
private boolean bind( List<Node> terms, Bindings<Node, Node> b )
{
return
this.terms.size() == terms.size()
&& bindTerms( this.terms, terms, b );
}
private boolean bindTerms( List<NodeTerm> these, List<Node> those, Bindings<Node, Node> b )
{
for (int i = 0; i < these.size(); i += 1)
{
if (!these.get( i ).bind( those.get( i ), b )) return false;
}
return true;
}
@Override public boolean isVariable()
{ return false; }
@Override public Node subst( ExecContext c, Bindings<Node, Node> b )
{
List<Node> resultTerms = new ArrayList<Node>();
for (NodeTerm t: terms) resultTerms.add( t.subst( c, b ) );
return new Functor( resultTerms );
}
@Override public String toString()
{ return "<functor " + node + ">"; }
}
public static class NodeTermConstant extends NodeTerm
{
public NodeTermConstant( Node node )
{ super( node ); }
@Override public Node subst( ExecContext c, Bindings<Node, Node> b )
{ return node; }
@Override public boolean bind( Node n, Bindings<Node, Node> b )
{ return node.equals( n ); }
@Override public String toString()
{ return "<lit " + node + ">"; }
@Override public boolean isVariable()
{ return false; }
}
public static class NodeTermExpr extends NodeTerm
{
protected final Applyable p;
public NodeTermExpr( Applyable p )
{
super( Node.ANY );
this.p = p;
}
@Override public String toString()
{ return "<expr " + p + ">"; }
@Override public boolean bind( Node n, Bindings<Node, Node> b )
{ throw new RuntimeException( "IMPLEMENT NodeTermExpr.bind" ); }
@Override public boolean isVariable()
{ throw new RuntimeException( "IMPLEMENT NodeTermExpr.isVariable" ); }
@Override public Node subst( ExecContext c, Bindings<Node, Node> b )
{
return p.evalNode( c, b );
}
}
public static class NodeTermVariable extends NodeTerm
{
public NodeTermVariable( Node node )
{ super( node ); }
@Override public Node subst( ExecContext c, Bindings<Node, Node> b )
{
Node result = b.get( node );
return result == null ? node : result;
}
@Override public boolean bind( Node n, Bindings<Node, Node> b )
{
Node bound = b.get( node );
if (bound == null)
{
b.set( node, n );
return true;
}
else
return bound.equals( n );
}
@Override public String toString()
{ return "<var " + node + ">"; }
@Override public boolean isVariable()
{ return true; }
}
public static NodeTerm createConstant( Node node )
{ return new NodeTermConstant( node ); }
public static NodeTerm createVariable( Node node )
{ return new NodeTermVariable( node ); }
public static NodeTerm createExpr( Applyable p )
{ return new NodeTermExpr( p ); }
public static NodeTerm create( Node n )
{
if (n instanceof Functor) return new NodeTermFunctor( n );
return n.isVariable() ? createVariable( n ) : createConstant( n );
}
}
/*
(c) Copyright 2008, 2009 Hewlett-Packard Development Company, LP
All rights reserved.
$Id$
*/