001    package org.maltparser.core.syntaxgraph.headrules;
002    
003    import java.util.ArrayList;
004    
005    import org.apache.log4j.Logger;
006    import org.maltparser.core.exception.MaltChainedException;
007    import org.maltparser.core.io.dataformat.ColumnDescription;
008    import org.maltparser.core.symbol.SymbolTable;
009    import org.maltparser.core.syntaxgraph.headrules.PrioSetMember.RelationToPrevMember;
010    import org.maltparser.core.syntaxgraph.node.NonTerminalNode;
011    import org.maltparser.core.syntaxgraph.node.PhraseStructureNode;
012    import org.maltparser.core.syntaxgraph.node.TokenNode;
013    /**
014    *
015    *
016    * @author Johan Hall
017    */
018    public class PrioSet extends ArrayList<PrioSetMember> {
019            public static final long serialVersionUID = 8045568022124816313L;
020            protected PrioList prioList;
021            protected PrioSetMember cache;
022            
023            public PrioSet(PrioList prioList) {
024                    setPrioList(prioList);
025                    cache = new PrioSetMember(this, null, null, -1, RelationToPrevMember.START);
026            }
027            
028            public PrioSet(PrioList prioList, String setSpec) throws MaltChainedException {
029                    setPrioList(prioList);
030                    cache = new PrioSetMember(this, null, null, -1, RelationToPrevMember.START);
031                    init(setSpec);
032            }
033            
034            public void init(String setSpec) throws MaltChainedException {
035                    String spec = setSpec.trim();
036                    String[] disItems = spec.split("\\|");
037                    for (int i = 0; i < disItems.length; i++) {
038                            String[] conItems = spec.split("\\&");
039                            for (int j = 0; j < conItems.length; j++) {
040                                    int index = conItems[j].indexOf(':');
041                                    if (index != -1) {
042                                            SymbolTable table = prioList.getDataFormatInstance().getSymbolTables().getSymbolTable(conItems[j].substring(0, index));
043                                            ColumnDescription column = prioList.getDataFormatInstance().getColumnDescriptionByName(conItems[j].substring(0, index));
044                                            if (i == 0 && j == 0) {
045                                                    addPrioSetMember(table, column, conItems[j].substring(index+1), RelationToPrevMember.START);
046                                            } else if (j == 0) {
047                                                    addPrioSetMember(table, column, conItems[j].substring(index+1), RelationToPrevMember.DISJUNCTION);
048                                            } else {
049                                                    addPrioSetMember(table, column, conItems[j].substring(index+1), RelationToPrevMember.CONJUNCTION);
050                                            }
051                                    } else {
052                                            throw new HeadRuleException("The specification of the priority list is not correct '"+setSpec+"'. ");
053                                    }
054                            }
055                    }
056            }
057            
058            public PrioSetMember addPrioSetMember(SymbolTable table, ColumnDescription column, String symbolString, RelationToPrevMember relationToPrevMember) throws MaltChainedException {
059                    if (table == null) {
060                            throw new HeadRuleException("Could add a member to priority set because the symbol table could be found. ");
061                    }
062                    return this.addPrioSetMember(table, column, table.addSymbol(symbolString), relationToPrevMember);
063            }
064            
065            public PrioSetMember addPrioSetMember(SymbolTable table, ColumnDescription column, int symbolCode, RelationToPrevMember relationToPrevMember) throws MaltChainedException {
066                    cache.setTable(table);
067                    cache.setSymbolCode(symbolCode);
068                    if (!contains(cache)) {
069                            PrioSetMember newItem = new PrioSetMember(this, table, column, symbolCode, relationToPrevMember);
070                            add(newItem);
071                            return newItem;
072                    }
073                    return cache;
074            }
075            
076            public PhraseStructureNode getHeadChild(NonTerminalNode nt, Direction direction) throws MaltChainedException {
077                    boolean match = false;
078                    if (direction == Direction.LEFT) {
079                            for (PhraseStructureNode child : nt.getChildren()) {
080                                    for (int j = 0; j < size(); j++) {
081                                            match = matchHeadChild(child, get(j));
082                                            if (match == true) {
083                                                    if (j+1 >= size()) {
084                                                            return child;
085                                                    } else if (get(j).getRelationToPrevMember() != RelationToPrevMember.CONJUNCTION) {
086                                                            return child;
087                                                    }
088                                            }
089                                    }
090                            }
091                    } else if (direction == Direction.RIGHT) {
092                            for (int i = nt.nChildren()-1; i >= 0; i--) {
093                                    PhraseStructureNode child = nt.getChild(i);
094                                    for (int j = 0; j < size(); j++) {
095                                            match = matchHeadChild(child, get(j));
096                                            if (match == true) {
097                                                    if (j+1 >= size()) {
098                                                            return child;
099                                                    } else if (get(j).getRelationToPrevMember() != RelationToPrevMember.CONJUNCTION) {
100                                                            return child;
101                                                    }
102                                            }
103                                    }
104                            }
105                    }
106                    return null;
107            }
108            
109            private boolean matchHeadChild(PhraseStructureNode child, PrioSetMember member) throws MaltChainedException {
110                    if (child instanceof NonTerminalNode && member.getTable().getName().equals("CAT") && member.getSymbolCode() == child.getLabelCode(member.getTable())) {
111                            return true;
112                    } else if (member.getTable().getName().equals("LABEL") && member.getSymbolCode() == child.getParentEdgeLabelCode(member.getTable())) {
113                            return true;
114                    } else if (child instanceof TokenNode && member.getColumn().getCategory() == ColumnDescription.INPUT && member.getSymbolCode() == child.getLabelCode(member.getTable())) {
115                            return true;
116                    }
117                    return false;
118            }
119            
120            public Logger getLogger() {
121                    return prioList.getLogger();
122            }
123    
124            public PrioList getPrioList() {
125                    return prioList;
126            }
127    
128            protected void setPrioList(PrioList prioList) {
129                    this.prioList = prioList;
130            }
131            
132            public boolean equals(Object obj) {
133                    if (this == obj)
134                            return true;
135                    if (obj == null)
136                            return false;
137                    if (getClass() != obj.getClass())
138                            return false;
139                    return super.equals(obj);
140            }
141            
142            public int hashCode() {
143                    return super.hashCode();
144            }
145            
146            public String toString() {
147                    final StringBuilder sb = new StringBuilder();
148                    for (int i = 0; i < size(); i++) {
149                            if (i != 0) {
150                                    if (get(i).getRelationToPrevMember() == RelationToPrevMember.CONJUNCTION) {
151                                            sb.append('&');
152                                    } else if (get(i).getRelationToPrevMember() == RelationToPrevMember.DISJUNCTION) {
153                                            sb.append('|');
154                                    }
155                            }
156                            sb.append(get(i));
157                    }
158                    return sb.toString();
159            }
160    }