blob: 2c4764c1159487538b86c6b270399ed4b61127fd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.reasoner.rulesys;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.Node_Variable ;
/**
* A variation on the normal Node_Variable which support for value bindings.
* Currently the forward rule system stores the values externally but requires
* variables to have an offset index in the rule environment vector. The
* variables can also support prolog-like reference chains and trails but these
* are not yet used.
* <p>
* Note that this should not be used in a real Triple, in particular
* it should not end up in a Graph. It is only needed for the rule systems. </p>
*/
public class Node_RuleVariable extends Node_Variable {
/** The offset of this variable in the Frule's binding table */
protected int index;
/** The value to which this variable is bound, can be another variable,
* itself (meaning unbound) or an actual value */
protected Node value;
/** A flag to indicate that the value is reference (pointer to a var) */
protected boolean isRef = true;
/** A static wildcard - like Node.ANY but tests equal to other Node_RuleVariables */
public static final Node_RuleVariable WILD = new Node_RuleVariable("*", -1);
/**
* Constructor
* @param label the text label for the variable
* @param index the calculated index of this variable in the rule
*/
public Node_RuleVariable(String label, int index) {
//super(label==null ? "" : label);
super(label);
this.index = index;
this.value = this;
}
/**
* Returns the variable's index in a binding vector.
* @return int
*/
public int getIndex() {
return index;
}
/**
* Changes the variable's index. This is used in LP rules which classify the
* variables into different sequences.
*/
public void setIndex(int index) {
this.index = index;
}
/**
* Return an indexable object for this Node. This is actually the
* rule label. This is weird but needed because equals is (deliberately)
* perverse on Node_RuleVariable so if we want to put then in a Set or Map
* we need something with a better equals function.
*/
// public Object getRepresentative() {
// return label;
// }
/**
* Binds a value to the brule version of the variable. Does not follow
* any reference trail, assues we have already been derefenced.
* @param node a concrete Node value or another Node_RuleVariable
* to alias to
*/
public void simpleBind(Node node) {
value = node;
isRef = node instanceof Node_RuleVariable;
}
/**
* Dereference a variable by following the reference chain.
* @return either a concrete node value or the last variable
* in the reference chain.
*/
public Node deref() {
Node_RuleVariable var = this;
while (var.isRef) {
if (var.value == var) {
return var;
}
var = (Node_RuleVariable)var.value;
}
return var.value;
}
/**
* Return the raw value to which this variable is bound (via LP binding) with
* no dereferencing.
*/
public Node getRawBoundValue() {
return value;
}
/**
* Set the variable to be unbound (in the brule sense)
*/
public void unbind() {
isRef = true;
value = this;
}
/**
* Test if the variable is unbound (in the brule sense).
*/
public boolean isUnbound() {
return (isRef && (value == this));
}
/**
* Clone the rule variable to allow multiple rule instaces to be active at the same time.
*/
public Node_RuleVariable cloneNode() {
return new Node_RuleVariable(getName(), index);
}
/** printable form */
@Override
public String toString() {
if (getName() == null) return "*";
return getName();
}
@Override
public boolean equals(Object o) {
if (o instanceof Node_RuleVariable) {
String name = getName();
if (name == null) {
return this == o;
} else {
return name.equals( ((Node_RuleVariable)o).getName() );
}
} else
return false;
}
@Override
public int hashCode() {
String name = getName();
if (name == null) {
return 0xc3a7;
} else {
return name.hashCode();
}
}
/**
* Test that two nodes are semantically equivalent.
*/
@Override
public boolean sameValueAs(Object o) {
return o instanceof Node_RuleVariable;
}
/**
* Compare two nodes, taking into account variable indices.
*/
public static boolean sameNodeAs(Node n, Node m) {
if (n instanceof Node_RuleVariable) {
if (m instanceof Node_RuleVariable) {
return ((Node_RuleVariable)n).getIndex() == ((Node_RuleVariable)m).getIndex();
} else {
return false;
}
} else {
return n.sameValueAs(m);
}
}
}