    001    package org.maltparser.core.syntaxgraph.ds2ps;
    002
    003
    004    import java.util.SortedMap;
    005
    006    import org.maltparser.core.exception.MaltChainedException;
    007    import org.maltparser.core.helper.SystemLogger;
    008    import org.maltparser.core.io.dataformat.ColumnDescription;
    009    import org.maltparser.core.io.dataformat.DataFormatInstance;
    010    import org.maltparser.core.symbol.SymbolTable;
    011    import org.maltparser.core.symbol.SymbolTableHandler;
    012    import org.maltparser.core.syntaxgraph.MappablePhraseStructureGraph;
    013    import org.maltparser.core.syntaxgraph.edge.Edge;
    014    import org.maltparser.core.syntaxgraph.headrules.HeadRules;
    015    import org.maltparser.core.syntaxgraph.node.DependencyNode;
    016    import org.maltparser.core.syntaxgraph.node.NonTerminalNode;
    017    import org.maltparser.core.syntaxgraph.node.PhraseStructureNode;
    018    /**
    019    *
    020    *
    021    * @author Johan Hall
    022    */
    023    public class LosslessMapping implements Dependency2PhraseStructure {
    024            private String DEPREL = "DEPREL";
    025            private String PHRASE = "PHRASE";
    026            private String HEADREL = "HEADREL";
    027            private String ATTACH = "ATTACH";
    028            private String CAT = "CAT";
    029            private String EDGELABEL;
    030            private final char EMPTY_SPINE = '*';
    031            private final String EMPTY_LABEL = "??";
    032            private final char SPINE_ELEMENT_SEPARATOR = '|';
    033            private final char LABEL_ELEMENT_SEPARATOR = '~';
    034            private final char QUESTIONMARK = '?';
    035            private String optionString;
    036            private HeadRules headRules;
    037            private DataFormatInstance dependencyDataFormatInstance;
    038            private DataFormatInstance phraseStructuretDataFormatInstance;
    039            private boolean lockUpdate = false;
    040            private int nonTerminalCounter;
    041            private StringBuilder deprel;
    042            private StringBuilder headrel;
    043            private StringBuilder phrase;
    044
    045            public LosslessMapping(DataFormatInstance dependencyDataFormatInstance, DataFormatInstance phraseStructuretDataFormatInstance) {
    046                    setDependencyDataFormatInstance(dependencyDataFormatInstance);
    047                    setPhraseStructuretDataFormatInstance(phraseStructuretDataFormatInstance);
    048                    deprel = new StringBuilder();
    049                    headrel = new StringBuilder();
    050                    phrase = new StringBuilder();
    051
    052                    if (phraseStructuretDataFormatInstance.getPhraseStructureEdgeLabelColumnDescriptionSet().size() == 1) {
    053                            for (ColumnDescription column : phraseStructuretDataFormatInstance.getPhraseStructureEdgeLabelColumnDescriptionSet()) {
    054                                    EDGELABEL = column.getName();
    055                            }
    056                    }
    057
    058                    clear();
    059            }
    060
    061            public void clear() {
    062                    nonTerminalCounter = 0;
    063            }
    064
    065            public String getOptionString() {
    066                    return optionString;
    067            }
    068
    069            public void setOptionString(String optionString) {
    070                    this.optionString = optionString;
    071            }
    072
    073            public DataFormatInstance getDependencyDataFormatInstance() {
    074                    return dependencyDataFormatInstance;
    075            }
    076
    077            public void setDependencyDataFormatInstance(
    078                            DataFormatInstance dependencyDataFormatInstance) {
    079                    this.dependencyDataFormatInstance = dependencyDataFormatInstance;
    080            }
    081
    082            public DataFormatInstance getPhraseStructuretDataFormatInstance() {
    083                    return phraseStructuretDataFormatInstance;
    084            }
    085
    086            public void setPhraseStructuretDataFormatInstance(
    087                            DataFormatInstance phraseStructuretDataFormatInstance) {
    088                    this.phraseStructuretDataFormatInstance = phraseStructuretDataFormatInstance;
    089            }
    090
    091            public void update(MappablePhraseStructureGraph graph, Edge e, Object arg) throws MaltChainedException {
    092                    if (lockUpdate == false) {
    093    //                      if (e.getType() == Edge.PHRASE_STRUCTURE_EDGE && e.getSource() instanceof NonTerminalNode && lockUpdate == false) {
    094    //                              if(e.getTarget() instanceof TerminalNode) {
    095    //                                      PhraseStructureNode top = (PhraseStructureNode)e.getTarget();
    096    //                                      while (top.getParent() != null && ((NonTerminalNode)top.getParent()).getLexicalHead() == (PhraseStructureNode)e.getTarget()) {
    097    //                                              top = top.getParent();
    098    //                                      }
    099    //                                      updateDependenyGraph(graph, top);
    100    //                              }
    101    //                              else if (e.getSource().isRoot()) {
    102    //                                      updateDependenyGraph(graph, graph.getPhraseStructureRoot());
    103    //                              }
    104    //                      }
    105                            if (e.getType() == Edge.DEPENDENCY_EDGE && e.getSource() instanceof DependencyNode && e.getTarget() instanceof DependencyNode) {
    106                                    if (e.isLabeled() && e.getLabelSet().size() == 4) {
    107                                            updatePhraseStructureGraph(graph, (Edge)e, false);
    108                                    }
    109                            }
    110                    }
    111            }
    112
    113            public void updateDependenyGraph(MappablePhraseStructureGraph graph, PhraseStructureNode top) throws MaltChainedException {
    114                    if (graph.nTokenNode() == 1 && graph.nNonTerminals() == 0) {
    115                            // Special case when the root dominates direct a single terminal node
    116                            Edge e = graph.addDependencyEdge(graph.getDependencyRoot(), graph.getDependencyNode(1));
    117                            e.addLabel(graph.getSymbolTables().getSymbolTable(DEPREL), graph.getDefaultRootEdgeLabelSymbol(graph.getSymbolTables().getSymbolTable(DEPREL)));
    118                            e.addLabel(graph.getSymbolTables().getSymbolTable(HEADREL), graph.getDefaultRootEdgeLabelSymbol(graph.getSymbolTables().getSymbolTable(HEADREL)));
    119                            e.addLabel(graph.getSymbolTables().getSymbolTable(PHRASE), "*");
    120    //                      e.addLabel(graph.getSymbolTables().getSymbolTable(PHRASE), graph.getDefaultRootEdgeLabelSymbol(graph.getSymbolTables().getSymbolTable(PHRASE)));
    121                            e.addLabel(graph.getSymbolTables().getSymbolTable(ATTACH), graph.getDefaultRootEdgeLabelSymbol(graph.getSymbolTables().getSymbolTable(ATTACH)));
    122                    } else {
    123                            updateDependencyEdges(graph, top);
    124                            updateDependenyLabels(graph);
    125                    }
    126            }
    127
    128
    129
    130            private void updateDependencyEdges(MappablePhraseStructureGraph graph, PhraseStructureNode top) throws MaltChainedException {
    131                    if (top == null) {
    132                            return;
    133                    }
    134                    DependencyNode head = null;
    135                    DependencyNode dependent = null;
    136                    if (top instanceof NonTerminalNode) {
    137                            for (PhraseStructureNode node : ((NonTerminalNode)top).getChildren()) {
    138                                    if (node instanceof NonTerminalNode) {
    139                                            updateDependencyEdges(graph,node);
    140                                    } else {
    141                                            head = ((NonTerminalNode)top).getLexicalHead(headRules);
    142                                            dependent = (DependencyNode)node;
    143                                            if (head != null && dependent != null && head != dependent) {
    144                                                    lockUpdate = true;
    145                                                    if (!dependent.hasHead()) {
    146                                                            graph.addDependencyEdge(head, dependent);
    147                                                    }
    148                                                    else if (head != dependent.getHead()) {
    149                                                            graph.moveDependencyEdge(head, dependent);
    150                                                    }
    151                                                    lockUpdate = false;
    152                                            }
    153                                    }
    154                            }
    155                    }
    156
    157                    head = null;
    158                    if (top.getParent() != null) {
    159                            head = ((NonTerminalNode)top.getParent()).getLexicalHead(headRules);
    160                    } else if (top.isRoot()) {
    161                            head = (DependencyNode)top;
    162                    }
    163
    164                    if (top instanceof NonTerminalNode) {
    165                            dependent = ((NonTerminalNode)top).getLexicalHead(headRules);
    166                    } else if (!top.isRoot()) {
    167                            dependent = (DependencyNode)top;
    168                    }
    169                    if (head != null && dependent != null && head != dependent) {
    170                            lockUpdate = true;
    171                            if (!dependent.hasHead()) {
    172                                    graph.addDependencyEdge(head, dependent);
    173                            }
    174                            else if (head != dependent.getHead()) {
    175                                    graph.moveDependencyEdge(head, dependent);
    176                            }
    177                            lockUpdate = false;
    178                    }
    179            }
    180
    181            private void updateDependenyLabels(MappablePhraseStructureGraph graph) throws MaltChainedException {
    182                    for (int index :graph.getTokenIndices()) {
    183                            PhraseStructureNode top = (PhraseStructureNode)graph.getTokenNode(index);
    184
    185                            while (top != null && top.getParent() != null &&graph.getTokenNode(index) == ((NonTerminalNode)top.getParent()).getLexicalHead(headRules)) {
    186                                    top = top.getParent();
    187                            }
    188                            lockUpdate = true;
    189                            labelDependencyEdge(graph, graph.getTokenNode(index).getHeadEdge(), top);
    190                            lockUpdate = false;
    191                    }
    192            }
    193
    194
    195    //      private void updateDependenyLabels(MappablePhraseStructureGraph graph, PhraseStructureNode top) throws MaltChainedException {
    196    //              if (top == null) {
    197    //                      return;
    198    //              }
    199    //              DependencyNode head = null;
    200    //              DependencyNode dependent = null;
    201    //              if (top instanceof NonTerminalNode) {
    202    //                      for (PhraseStructureNode node : ((NonTerminalNode)top).getChildren()) {
    203    //                              if (node instanceof NonTerminalNode) {
    204    //                                      updateDependenyLabels(graph, node);
    205    //                              } else {
    206    //                                      head = ((NonTerminalNode)top).getLexicalHead(headRules);
    207    //                                      dependent = (DependencyNode)node;
    208    //                                      if (head != null && dependent != null && head != dependent) {
    209    //                                              lockUpdate = true;
    210    //                                              if (dependent.hasHead()) {
    211    //                                                      Edge e = dependent.getHeadEdge();
    212    //                                                      labelDependencyEdge(graph, e, node);
    213    //                                              }
    214    //                                              lockUpdate = false;
    215    //                                      }
    216    //                              }
    217    //                      }
    218    //              }
    219    //
    220    //              dependent = null;
    221    //              if (top instanceof NonTerminalNode) {
    222    //                      dependent = ((NonTerminalNode)top).getLexicalHead(headRules);
    223    //              }
    224    //
    225    //              if (dependent != null) {
    226    //                      lockUpdate = true;
    227    //                      if (dependent.hasHead()) {
    228    //                              Edge e = dependent.getHeadEdge();
    229    //                              labelDependencyEdge(graph, e, top);
    230    //                      }
    231    //                      lockUpdate = false;
    232    //              }
    233    //      }
    234
    235            private void labelDependencyEdge(MappablePhraseStructureGraph graph, Edge e, PhraseStructureNode top) throws MaltChainedException {
    236                    if  (e == null) {
    237                            return;
    238                    }
    239                    SymbolTableHandler symbolTables = graph.getSymbolTables();
    240                    deprel.setLength(0);
    241                    phrase.setLength(0);
    242                    headrel.setLength(0);
    243
    244                    e.removeLabel(symbolTables.getSymbolTable(DEPREL));
    245                    e.removeLabel(symbolTables.getSymbolTable(HEADREL));
    246                    e.removeLabel(symbolTables.getSymbolTable(PHRASE));
    247                    e.removeLabel(symbolTables.getSymbolTable(ATTACH));
    248
    249                    int i = 0;
    250                    SortedMap<String, SymbolTable> edgeLabelSymbolTables = phraseStructuretDataFormatInstance.getPhraseStructureEdgeLabelSymbolTables();
    251                    SortedMap<String, SymbolTable> nodeLabelSymbolTables = phraseStructuretDataFormatInstance.getPhraseStructureNodeLabelSymbolTables();
    252                    if (!top.isRoot()) {
    253                            for (String name : edgeLabelSymbolTables.keySet()) {
    254                                    if (top.hasParentEdgeLabel(symbolTables.getSymbolTable(name))) {
    255                                            deprel.append(top.getParentEdgeLabelSymbol(symbolTables.getSymbolTable(name)));
    256                                    } else {
    257                                            deprel.append(EMPTY_LABEL);
    258                                    }
    259                                    i++;
    260                                    if (i < edgeLabelSymbolTables.size()) {
    261                                            deprel.append(LABEL_ELEMENT_SEPARATOR);
    262                                    }
    263                            }
    264                            if (deprel.length() != 0) {
    265                                    e.addLabel(symbolTables.getSymbolTable(DEPREL), deprel.toString());
    266                            }
    267                    } else {
    268                            String deprelDefaultRootLabel = graph.getDefaultRootEdgeLabelSymbol(symbolTables.getSymbolTable(DEPREL));
    269                            if (deprelDefaultRootLabel != null) {
    270                                    e.addLabel(symbolTables.getSymbolTable(DEPREL), deprelDefaultRootLabel);
    271                            } else {
    272                                    e.addLabel(symbolTables.getSymbolTable(DEPREL), EMPTY_LABEL);
    273                            }
    274                    }
    275                    PhraseStructureNode tmp = (PhraseStructureNode)e.getTarget();
    276                    while (tmp != top && tmp.getParent() != null) { // && !tmp.getParent().isRoot()) {
    277                            i=0;
    278                            for (String name : edgeLabelSymbolTables.keySet()) {
    279                                    if (tmp.hasParentEdgeLabel(symbolTables.getSymbolTable(name))) {
    280                                            headrel.append(tmp.getParentEdgeLabelSymbol(symbolTables.getSymbolTable(name)));
    281                                    } else {
    282                                            headrel.append(EMPTY_LABEL);
    283                                    }
    284                                    i++;
    285                                    if (i < edgeLabelSymbolTables.size()) {
    286                                            headrel.append(LABEL_ELEMENT_SEPARATOR);
    287                                    }
    288                            }
    289                            i=0;
    290                            headrel.append(SPINE_ELEMENT_SEPARATOR);
    291                            for (String name : nodeLabelSymbolTables.keySet()) {
    292                                    if (tmp.getParent().hasLabel(symbolTables.getSymbolTable(name))) {
    293                                            phrase.append(tmp.getParent().getLabelSymbol(symbolTables.getSymbolTable(name)));
    294                                    } else {
    295                                            if (tmp.getParent().isRoot()) {
    296                                                    String deprelDefaultRootLabel = graph.getDefaultRootEdgeLabelSymbol(symbolTables.getSymbolTable(PHRASE));
    297                                                    if (deprelDefaultRootLabel != null) {
    298                                                            phrase.append(deprelDefaultRootLabel);
    299                                                    } else {
    300                                                            phrase.append(EMPTY_LABEL);
    301                                                    }
    302                                            } else {
    303                                                    phrase.append(EMPTY_LABEL);
    304                                            }
    305                                    }
    306                                    i++;
    307                                    if (i < nodeLabelSymbolTables.size()) {
    308                                            phrase.append(LABEL_ELEMENT_SEPARATOR);
    309                                    }
    310                            }
    311                            phrase.append(SPINE_ELEMENT_SEPARATOR);
    312                            tmp = tmp.getParent();
    313                    }
    314                    if (phrase.length() == 0) {
    315                            headrel.append(EMPTY_SPINE);
    316                            phrase.append(EMPTY_SPINE);
    317                    } else {
    318                            headrel.setLength(headrel.length()-1);
    319                            phrase.setLength(phrase.length()-1);
    320                    }
    321                    e.addLabel(symbolTables.getSymbolTable(HEADREL), headrel.toString());
    322                    e.addLabel(symbolTables.getSymbolTable(PHRASE), phrase.toString());
    323                    int a = 0;
    324                    tmp = (PhraseStructureNode)e.getSource();
    325                    while (top.getParent() != null && tmp.getParent() != null && tmp.getParent() != top.getParent()) {
    326                            a++;
    327                            tmp = tmp.getParent();
    328                    }
    329                    e.addLabel(symbolTables.getSymbolTable(ATTACH), Integer.toString(a));
    330            }
    331
    332            public void connectUnattachedSpines(MappablePhraseStructureGraph graph) throws MaltChainedException {
    333                    connectUnattachedSpines(graph, graph.getDependencyRoot());
    334
    335                    if (!graph.getPhraseStructureRoot().isLabeled()) {
    336                            graph.getPhraseStructureRoot().addLabel(graph.getSymbolTables().addSymbolTable(CAT), graph.getDefaultRootEdgeLabelSymbol(graph.getSymbolTables().getSymbolTable(PHRASE)));
    337
    338                    }
    339            }
    340
    341            private void connectUnattachedSpines(MappablePhraseStructureGraph graph, DependencyNode depNode) throws MaltChainedException {
    342                    if (!depNode.isRoot()) {
    343                            PhraseStructureNode dependentSpine = (PhraseStructureNode)depNode;
    344                            while (dependentSpine.getParent() != null) {
    345                                    dependentSpine = dependentSpine.getParent();
    346                            }
    347                            if (!dependentSpine.isRoot()) {
    348                                    updatePhraseStructureGraph(graph,depNode.getHeadEdge(),true);
    349                            }
    350                    }
    351                    for (int i = 0; i < depNode.getLeftDependentCount(); i++) {
    352                            connectUnattachedSpines(graph, depNode.getLeftDependent(i));
    353                    }
    354                    for (int i = depNode.getRightDependentCount()-1; i >= 0 ; i--) {
    355                            connectUnattachedSpines(graph, depNode.getRightDependent(i));
    356                    }
    357            }
    358
    359            public void updatePhraseStructureGraph(MappablePhraseStructureGraph graph, Edge depEdge, boolean attachHeadSpineToRoot) throws MaltChainedException {
    360                    PhraseStructureNode dependentSpine = (PhraseStructureNode)depEdge.getTarget();
    361
    362                    if (((PhraseStructureNode)depEdge.getTarget()).getParent() == null) {
    363                            // Restore dependent spine
    364                            String phraseSpineLabel = null;
    365                            String edgeSpineLabel = null;
    366                            int empty_label = 0;
    367
    368                            if (depEdge.hasLabel(graph.getSymbolTables().getSymbolTable(PHRASE))) {
    369                                    phraseSpineLabel = depEdge.getLabelSymbol(graph.getSymbolTables().getSymbolTable(PHRASE));
    370                            }
    371                            if (depEdge.hasLabel(graph.getSymbolTables().getSymbolTable(HEADREL))) {
    372                                    edgeSpineLabel = depEdge.getLabelSymbol(graph.getSymbolTables().getSymbolTable(HEADREL));
    373                            }
    374                            if (phraseSpineLabel != null && phraseSpineLabel.length() > 0 && phraseSpineLabel.charAt(0) != EMPTY_SPINE) {
    375                                    int ps = 0, es = 0, i = 0, j = 0, n = phraseSpineLabel.length()-1, m = edgeSpineLabel.length()-1;
    376                                    PhraseStructureNode child = (PhraseStructureNode)depEdge.getTarget();
    377                                    while (true) {
    378                                            while (i <= n && phraseSpineLabel.charAt(i) != SPINE_ELEMENT_SEPARATOR) {
    379                                                    if (phraseSpineLabel.charAt(i) == QUESTIONMARK) {
    380                                                            empty_label++;
    381                                                    } else {
    382                                                            empty_label = 0;
    383                                                    }
    384                                                    i++;
    385                                            }
    386                                            if (depEdge.getSource().isRoot() && i >= n) {
    387                                                    dependentSpine = graph.getPhraseStructureRoot();
    388                                            } else {
    389                                                    dependentSpine = graph.addNonTerminalNode(++nonTerminalCounter);
    390                                            }
    391
    392                                            if (empty_label != 2 && ps != i) {
    393                                                    dependentSpine.addLabel(graph.getSymbolTables().addSymbolTable(CAT), phraseSpineLabel.substring(ps,i));
    394                                            }
    395
    396                                            empty_label = 0;
    397                                            if (edgeSpineLabel != null) {
    398                                                    while (j <= m && edgeSpineLabel.charAt(j) != SPINE_ELEMENT_SEPARATOR) {
    399                                                            if (edgeSpineLabel.charAt(j) == QUESTIONMARK) {
    400                                                                    empty_label++;
    401                                                            } else {
    402                                                                    empty_label = 0;
    403                                                            }
    404                                                            j++;
    405                                                    }
    406                                            }
    407                                            lockUpdate = true;
    408                                            Edge e = graph.addPhraseStructureEdge(dependentSpine, child);
    409                                            if (empty_label != 2 && es != j && edgeSpineLabel != null  && e != null) {
    410                                                    e.addLabel(graph.getSymbolTables().addSymbolTable(EDGELABEL), edgeSpineLabel.substring(es,j));
    411                                            } else if (es == j) {
    412                                                    e.addLabel(graph.getSymbolTables().addSymbolTable(EDGELABEL), EMPTY_LABEL);
    413                                            }
    414
    415                                            lockUpdate = false;
    416                                            child = dependentSpine;
    417                                            if (i >= n) { break; }
    418                                            empty_label = 0;
    419                                            ps = i = i + 1;
    420                                            es = j = j + 1;
    421                                    }
    422                            }
    423
    424                            // Recursively attach the dependent spines to target node.
    425                            DependencyNode target = (DependencyNode)depEdge.getTarget();
    426                            for (int i = 0; i < target.getLeftDependentCount(); i++) {
    427                                    updatePhraseStructureGraph(graph, target.getLeftDependent(i).getHeadEdge(), attachHeadSpineToRoot);
    428                            }
    429                            for (int i = target.getRightDependentCount()-1; i >= 0 ; i--) {
    430                                    updatePhraseStructureGraph(graph, target.getRightDependent(i).getHeadEdge(), attachHeadSpineToRoot);
    431                            }
    432                    } else {
    433                            // If dependent spine already exist, then set dependentSpine to the highest nonterminal
    434                            // of the dependent spine.
    435                            while (dependentSpine.getParent() != null && !dependentSpine.getParent().isRoot()) {
    436                                    dependentSpine = dependentSpine.getParent();
    437                            }
    438                    }
    439
    440
    441                    PhraseStructureNode headSpine = null;
    442                    if (((PhraseStructureNode)depEdge.getSource()).getParent() != null) {
    443                            // If head spine exist, then attach dependent spine to the head spine at the attachment level a.
    444                            int a = 0;
    445                            headSpine = ((PhraseStructureNode)depEdge.getSource()).getParent();
    446                            if (depEdge.hasLabel(graph.getSymbolTables().getSymbolTable(ATTACH))) {
    447                                    try {
    448                                    a = Integer.parseInt((depEdge.getLabelSymbol(graph.getSymbolTables().getSymbolTable(ATTACH))));
    449                                    } catch (NumberFormatException e) {
    450                                            throw new MaltChainedException(e.getMessage());
    451                                    }
    452                            }
    453                            for (int i = 0; i < a && headSpine != null; i++) {
    454                                    headSpine = headSpine.getParent();
    455                            }
    456
    457                            if ((headSpine == null || headSpine == dependentSpine) && attachHeadSpineToRoot) {
    458                                    headSpine = graph.getPhraseStructureRoot();
    459                            }
    460                            if (headSpine != null) {
    461                                    lockUpdate = true;
    462                                    Edge e = graph.addPhraseStructureEdge(headSpine, dependentSpine);
    463                                    if (depEdge.hasLabel(graph.getSymbolTables().getSymbolTable(DEPREL)) && !depEdge.getLabelSymbol(graph.getSymbolTables().getSymbolTable(DEPREL)).equals(EMPTY_LABEL) & e != null) {
    464                                            e.addLabel(graph.getSymbolTables().addSymbolTable(EDGELABEL), depEdge.getLabelSymbol(graph.getSymbolTables().getSymbolTable(DEPREL)));
    465                                    }
    466                                    lockUpdate = false;
    467                            }
    468                    }
    469                    else if (depEdge.getSource().isRoot() && !depEdge.isLabeled()) {
    470                                    headSpine = graph.getPhraseStructureRoot();
    471                                    lockUpdate = true;
    472                                    Edge e = graph.addPhraseStructureEdge(headSpine, dependentSpine);
    473                                    if (depEdge.hasLabel(graph.getSymbolTables().getSymbolTable(DEPREL)) && !depEdge.getLabelSymbol(graph.getSymbolTables().getSymbolTable(DEPREL)).equals(EMPTY_LABEL) & e != null) {
    474                                            e.addLabel(graph.getSymbolTables().addSymbolTable(EDGELABEL), depEdge.getLabelSymbol(graph.getSymbolTables().getSymbolTable(DEPREL)));
    475                                    } else {
    476                                            e.addLabel(graph.getSymbolTables().addSymbolTable(EDGELABEL), graph.getDefaultRootEdgeLabelSymbol(graph.getSymbolTables().getSymbolTable(DEPREL)));
    477                                    }
    478                                    lockUpdate = false;
    479                                    // Recursively attach the dependent spines to target node.
    480                                    DependencyNode target = (DependencyNode)depEdge.getTarget();
    481                                    for (int i = 0; i < target.getLeftDependentCount(); i++) {
    482                                            updatePhraseStructureGraph(graph, target.getLeftDependent(i).getHeadEdge(), attachHeadSpineToRoot);
    483                                    }
    484                                    for (int i = target.getRightDependentCount()-1; i >= 0 ; i--) {
    485                                            updatePhraseStructureGraph(graph, target.getRightDependent(i).getHeadEdge(), attachHeadSpineToRoot);
    486                                    }
    487                    }
    488            }
    489
    490            public HeadRules getHeadRules() {
    491                    return headRules;
    492            }
    493
    494            public void setHeadRules(HeadRules headRules) {
    495                    this.headRules = headRules;
    496            }
    497
    498            public void setHeadRules(String headRulesURL) throws MaltChainedException {
    499                    if (headRulesURL != null && headRulesURL.length() > 0 && !headRulesURL.equals("*")) {
    500                            headRules = new HeadRules(SystemLogger.logger(), phraseStructuretDataFormatInstance);
    501                            headRules.parseHeadRules(headRulesURL);
    502                    }
    503            }
    504    }