001package org.maltparser.core.syntaxgraph.headrules;
002
003import java.util.ArrayList;
004
005import org.apache.log4j.Logger;
006import org.maltparser.core.exception.MaltChainedException;
007import org.maltparser.core.io.dataformat.ColumnDescription;
008import org.maltparser.core.symbol.SymbolTable;
009import org.maltparser.core.syntaxgraph.headrules.PrioSetMember.RelationToPrevMember;
010import org.maltparser.core.syntaxgraph.node.NonTerminalNode;
011import org.maltparser.core.syntaxgraph.node.PhraseStructureNode;
012import org.maltparser.core.syntaxgraph.node.TokenNode;
013/**
014*
015*
016* @author Johan Hall
017*/
018public 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.getSymbolTableHandler().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}