package edu.stanford.nlp.trees; import edu.stanford.nlp.ling.Label; import edu.stanford.nlp.ling.StringLabel; import edu.stanford.nlp.util.ErasureUtils; import edu.stanford.nlp.util.XMLUtils; /** * An individual dependency between a head and a dependent. * The head and dependent are represented as a Label. * For example, these can be a * Word or a WordTag. If one wishes the dependencies to preserve positions * in a sentence, then each can be a NamedConstituent. * * @author Christopher Manning */ public class NamedDependency implements Dependency<Label, Label, Object> { private Label regent; private Label dependent; private Object name; @Override public int hashCode() { return regent.hashCode() ^ dependent.hashCode() ^ name.hashCode(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o instanceof NamedDependency) { NamedDependency d = (NamedDependency) o; return governor().equals(d.governor()) && dependent().equals(d.dependent()); } return false; } public boolean equalsIgnoreName(Object o) { if (this == o) { return true; } if (o instanceof Dependency) { Dependency<Label, Label, Object> d = ErasureUtils.<Dependency<Label, Label, Object>>uncheckedCast(o); return governor().equals(d.governor()) && dependent().equals(d.dependent()); } return false; } @Override public String toString() { return regent + " --" + name + "--> " + dependent; } /** * Provide different printing options via a String keyword. * The recognized options are currently "xml", and "predicate". * Otherwise the default toString() is used. */ public String toString(String format) { if ("xml".equals(format)) { return "<dep type=\"" + XMLUtils.escapeXML(name().toString()) + "\">\n <governor>" + XMLUtils.escapeXML(governor().value()) + "</governor>\n <dependent>" + XMLUtils.escapeXML(dependent().value()) + "</dependent>\n </dep>"; } else if ("predicate".equals(format)) { return name() + "(" + governor() + "," + dependent() + ")"; } else { return toString(); } } public NamedDependency(String regent, String dependent, Object name) { this(new StringLabel(regent), new StringLabel(dependent), name); } public NamedDependency(String regent, int regentIndex, String dependent, int dependentIndex, Object name) { this(regent, regentIndex, regentIndex + 1, dependent, dependentIndex, dependentIndex + 1, name); } public NamedDependency(String regent, int regentStartIndex, int regentEndIndex, String dependent, int depStartIndex, int depEndIndex, Object name) { this(new LabeledConstituent(regentStartIndex, regentEndIndex, regent), new LabeledConstituent(depStartIndex, depEndIndex, dependent), name); } public NamedDependency(Label regent, Label dependent, Object name) { if (regent == null || dependent == null) { throw new IllegalArgumentException("governor or dependent cannot be null"); } this.regent = regent; this.dependent = dependent; this.name = name; } public Label governor() { return regent; } public Label dependent() { return dependent; } public Object name() { return name; } public DependencyFactory dependencyFactory() { return DependencyFactoryHolder.df; } public static DependencyFactory factory() { return DependencyFactoryHolder.df; } // extra class guarantees correct lazy loading (Bloch p.194) private static class DependencyFactoryHolder { private static final DependencyFactory df = new NamedDependencyFactory(); } /** * A <code>DependencyFactory</code> acts as a factory for creating objects * of class <code>Dependency</code> */ private static class NamedDependencyFactory implements DependencyFactory { public NamedDependencyFactory() { } /** * Create a new <code>Dependency</code>. */ public Dependency<Label, Label, Object> newDependency(Label regent, Label dependent) { return newDependency(regent, dependent, null); } /** * Create a new <code>Dependency</code>. */ public Dependency<Label, Label, Object> newDependency(Label regent, Label dependent, Object name) { return new NamedDependency(regent, dependent, name); } } private static final long serialVersionUID = 5; }