package edu.stanford.nlp.trees;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.ling.Label;
import edu.stanford.nlp.ling.LabelFactory;
/**
* A {@code LabeledScoredTreeNode} represents a tree composed of a root
* label, a score,
* and an array of daughter parse trees. A parse tree derived from a rule
* provides information about the category of the root as well as a composite
* of the daughter categories.
*
* @author Christopher Manning
*/
public class LabeledScoredTreeNode extends Tree {
private static final long serialVersionUID = -8992385140984593817L;
/**
* Label of the parse tree.
*/
private Label label; // = null;
/**
* Score of <code>TreeNode</code>
*/
private double score = Double.NaN;
/**
* Daughters of the parse tree.
*/
private Tree[] daughterTrees; // = null;
/**
* Create an empty parse tree.
*/
public LabeledScoredTreeNode() {
setChildren(EMPTY_TREE_ARRAY);
}
/**
* Create a leaf parse tree with given word.
*
* @param label the <code>Label</code> representing the <i>word</i> for
* this new tree leaf.
*/
public LabeledScoredTreeNode(Label label) {
this(label, Double.NaN);
}
/**
* Create a leaf parse tree with given word and score.
*
* @param label The <code>Label</code> representing the <i>word</i> for
* @param score The score for the node
* this new tree leaf.
*/
public LabeledScoredTreeNode(Label label, double score) {
this();
this.label = label;
this.score = score;
}
/**
* Create parse tree with given root and array of daughter trees.
*
* @param label root label of tree to construct.
* @param daughterTreesList List of daughter trees to construct.
*/
public LabeledScoredTreeNode(Label label, List<Tree> daughterTreesList) {
this.label = label;
setChildren(daughterTreesList);
}
/**
* Returns an array of children for the current node, or null
* if it is a leaf.
*/
@Override
public Tree[] children() {
return daughterTrees;
}
/**
* Sets the children of this <code>Tree</code>. If given
* <code>null</code>, this method sets the Tree's children to
* the canonical zero-length Tree[] array.
*
* @param children An array of child trees
*/
@Override
public void setChildren(Tree[] children) {
if (children == null) {
daughterTrees = EMPTY_TREE_ARRAY;
} else {
daughterTrees = children;
}
}
/**
* Returns the label associated with the current node, or null
* if there is no label
*/
@Override
public Label label() {
return label;
}
/**
* Sets the label associated with the current node, if there is one.
*/
@Override
public void setLabel(final Label label) {
this.label = label;
}
/**
* Returns the score associated with the current node, or Nan
* if there is no score
*/
@Override
public double score() {
return score;
}
/**
* Sets the score associated with the current node, if there is one
*/
@Override
public void setScore(double score) {
this.score = score;
}
/**
* Return a <code>TreeFactory</code> that produces trees of the
* same type as the current <code>Tree</code>. That is, this
* implementation, will produce trees of type
* <code>LabeledScoredTree(Node|Leaf)</code>.
* The <code>Label</code> of <code>this</code>
* is examined, and providing it is not <code>null</code>, a
* <code>LabelFactory</code> which will produce that kind of
* <code>Label</code> is supplied to the <code>TreeFactory</code>.
* If the <code>Label</code> is <code>null</code>, a
* <code>StringLabelFactory</code> will be used.
* The factories returned on different calls a different: a new one is
* allocated each time.
*
* @return a factory to produce labeled, scored trees
*/
@Override
public TreeFactory treeFactory() {
LabelFactory lf = (label() == null) ? CoreLabel.factory() : label().labelFactory();
return new LabeledScoredTreeFactory(lf);
}
// extra class guarantees correct lazy loading (Bloch p.194)
private static class TreeFactoryHolder {
static final TreeFactory tf = new LabeledScoredTreeFactory();
}
/**
* Return a <code>TreeFactory</code> that produces trees of the
* <code>LabeledScoredTree{Node|Leaf}</code> type.
* The factory returned is always the same one (a singleton).
*
* @return a factory to produce labeled, scored trees
*/
public static TreeFactory factory() {
return TreeFactoryHolder.tf;
}
/**
* Return a <code>TreeFactory</code> that produces trees of the
* <code>LabeledScoredTree{Node|Leaf}</code> type, with
* the <code>Label</code> made with the supplied
* <code>LabelFactory</code>.
* The factory returned is a different one each time
*
* @param lf The LabelFactory to use
* @return a factory to produce labeled, scored trees
*/
public static TreeFactory factory(LabelFactory lf) {
return new LabeledScoredTreeFactory(lf);
}
private static final NumberFormat nf = new DecimalFormat("0.000");
@Override
public String nodeString() {
StringBuilder buff = new StringBuilder();
buff.append(super.nodeString());
if ( ! Double.isNaN(score)) {
buff.append(" [").append(nf.format(-score)).append("]");
}
return buff.toString();
}
}