001package org.maltparser.parser;
002
003
004import java.util.regex.Pattern;
005
006import org.maltparser.core.exception.MaltChainedException;
007import org.maltparser.core.helper.HashMap;
008import org.maltparser.core.propagation.PropagationManager;
009import org.maltparser.core.symbol.SymbolTable;
010import org.maltparser.core.symbol.SymbolTableHandler;
011import org.maltparser.core.symbol.Table;
012import org.maltparser.core.symbol.TableHandler;
013import org.maltparser.core.syntaxgraph.DependencyStructure;
014import org.maltparser.core.syntaxgraph.LabelSet;
015import org.maltparser.core.syntaxgraph.edge.Edge;
016import org.maltparser.parser.history.GuideUserHistory;
017import org.maltparser.parser.history.action.GuideUserAction;
018import org.maltparser.parser.history.container.ActionContainer;
019import org.maltparser.parser.transition.TransitionTable;
020import org.maltparser.parser.transition.TransitionTableHandler;
021/**
022 * @author Johan Hall
023 *
024 */
025public abstract class TransitionSystem {
026        public final static Pattern decisionSettingsSplitPattern = Pattern.compile(",|#|;|\\+");
027        private final HashMap<String, TableHandler> tableHandlers;
028        private final PropagationManager propagationManager;
029        protected final TransitionTableHandler transitionTableHandler;
030        protected ActionContainer[] actionContainers;
031        protected ActionContainer transActionContainer;
032        protected ActionContainer[] arcLabelActionContainers;
033        
034        
035        public TransitionSystem(PropagationManager _propagationManager) throws MaltChainedException {   
036                this.transitionTableHandler = new TransitionTableHandler();
037                this.tableHandlers = new HashMap<String, TableHandler>();
038                this.propagationManager = _propagationManager;
039        }
040        
041        public abstract void apply(GuideUserAction currentAction, ParserConfiguration config) throws MaltChainedException;
042        public abstract boolean permissible(GuideUserAction currentAction, ParserConfiguration config) throws MaltChainedException;
043        public abstract GuideUserAction getDeterministicAction(GuideUserHistory history, ParserConfiguration config) throws MaltChainedException;
044        protected abstract void addAvailableTransitionToTable(TransitionTable ttable) throws MaltChainedException;
045        protected abstract void initWithDefaultTransitions(GuideUserHistory history) throws MaltChainedException;
046        public abstract String getName();
047        public abstract GuideUserAction defaultAction(GuideUserHistory history, ParserConfiguration configuration) throws MaltChainedException;
048        
049        protected GuideUserAction updateActionContainers(GuideUserHistory history, int transition, LabelSet arcLabels) throws MaltChainedException {    
050                transActionContainer.setAction(transition);
051
052                if (arcLabels == null) {
053                        for (int i = 0; i < arcLabelActionContainers.length; i++) {
054                                arcLabelActionContainers[i].setAction(-1);      
055                        }
056                } else {
057                        for (int i = 0; i < arcLabelActionContainers.length; i++) {
058                                if (arcLabelActionContainers[i] == null) {
059                                        throw new MaltChainedException("arcLabelActionContainer " + i + " is null when doing transition " + transition);
060                                }
061                                
062                                Integer code = arcLabels.get(arcLabelActionContainers[i].getTable());
063                                if (code != null) {
064                                        arcLabelActionContainers[i].setAction(code.shortValue());
065                                } else {
066                                        arcLabelActionContainers[i].setAction(-1);
067                                }
068                        }               
069                }
070                GuideUserAction oracleAction = history.getEmptyGuideUserAction();
071                oracleAction.addAction(actionContainers);
072                return oracleAction;
073        }
074        
075        protected boolean isActionContainersLabeled() {
076                for (int i = 0; i < arcLabelActionContainers.length; i++) {
077                        if (arcLabelActionContainers[i].getActionCode() < 0) {
078                                return false;
079                        }
080                }
081                return true;
082        }
083        
084        protected void addEdgeLabels(Edge e) throws MaltChainedException {
085                if (e != null) { 
086                        for (int i = 0; i < arcLabelActionContainers.length; i++) {
087                                if (arcLabelActionContainers[i].getActionCode() != -1) {
088                                        e.addLabel((SymbolTable)arcLabelActionContainers[i].getTable(), arcLabelActionContainers[i].getActionCode());
089                                } else {
090                                        e.addLabel((SymbolTable)arcLabelActionContainers[i].getTable(), ((DependencyStructure)e.getBelongsToGraph()).getDefaultRootEdgeLabelCode((SymbolTable)arcLabelActionContainers[i].getTable()));
091                                }
092                        }
093                        if (propagationManager != null) {
094                                propagationManager.propagate(e);
095                        }
096                }
097        }
098        
099        public void initTransitionSystem(GuideUserHistory history) throws MaltChainedException {
100                this.actionContainers = history.getActionContainerArray();
101                if (actionContainers.length < 1) {
102                        throw new ParsingException("Problem when initialize the history (sequence of actions). There are no action containers. ");
103                }
104                int nLabels = 0;
105                for (int i = 0; i < actionContainers.length; i++) {
106                        if (actionContainers[i].getTableContainerName().startsWith("A.")) {
107                                nLabels++;
108                        }
109                }
110                int j = 0;
111                for (int i = 0; i < actionContainers.length; i++) {
112                        if (actionContainers[i].getTableContainerName().equals("T.TRANS")) {
113                                transActionContainer = actionContainers[i];
114                        } else if (actionContainers[i].getTableContainerName().startsWith("A.")) {
115                                if (arcLabelActionContainers == null) {
116                                        arcLabelActionContainers = new ActionContainer[nLabels];
117                                }
118                                arcLabelActionContainers[j++] = actionContainers[i];
119                        }
120                }
121                initWithDefaultTransitions(history);
122        }
123        
124        public void initTableHandlers(String decisionSettings, SymbolTableHandler symbolTableHandler) throws MaltChainedException {
125                if (decisionSettings.equals("T.TRANS+A.DEPREL") || decisionSettings.equals("T.TRANS#A.DEPREL") || decisionSettings.equals("T.TRANS,A.DEPREL") || decisionSettings.equals("T.TRANS;A.DEPREL")) {
126                        tableHandlers.put("T", transitionTableHandler);
127                        addAvailableTransitionToTable((TransitionTable)transitionTableHandler.addSymbolTable("TRANS"));
128                        tableHandlers.put("A", symbolTableHandler);
129                        return;
130                }
131                initTableHandlers(decisionSettingsSplitPattern.split(decisionSettings), decisionSettings, symbolTableHandler);
132        }
133        
134        public void initTableHandlers(String[] decisionElements, String decisionSettings, SymbolTableHandler symbolTableHandler) throws MaltChainedException {
135                int nTrans = 0;
136                for (int i = 0; i < decisionElements.length; i++) {
137                        int index = decisionElements[i].indexOf('.');
138                        if (index == -1) {
139                                throw new ParsingException("Decision settings '"+decisionSettings+"' contain an item '"+decisionElements[i]+"' that does not follow the format {TableHandler}.{Table}. ");
140                        }
141                        if (decisionElements[i].substring(0,index).equals("T")) {
142                                if (!tableHandlers.containsKey("T")) {
143                                        tableHandlers.put("T", transitionTableHandler);
144                                }
145                                if (decisionElements[i].substring(index+1).equals("TRANS")) {
146                                        if (nTrans == 0) {
147                                                addAvailableTransitionToTable((TransitionTable)transitionTableHandler.addSymbolTable("TRANS"));
148                                        } else {
149                                                throw new ParsingException("Illegal decision settings '"+decisionSettings+"'");
150                                        }
151                                        nTrans++;
152                                }  
153                        } else if (decisionElements[i].substring(0,index).equals("A")) {
154                                if (!tableHandlers.containsKey("A")) {
155                                        tableHandlers.put("A", symbolTableHandler);
156                                }
157                        } else {
158                                throw new ParsingException("The decision settings '"+decisionSettings+"' contains an unknown table handler '"+decisionElements[i].substring(0,index)+"'. " +
159                                                "Only T (Transition table handler) and A (ArcLabel table handler) is allowed. ");
160                        }
161                }
162        }
163        
164        public void copyAction(GuideUserAction source, GuideUserAction target) throws MaltChainedException {
165                source.getAction(actionContainers);
166                target.addAction(actionContainers);
167        }
168        
169        public HashMap<String, TableHandler> getTableHandlers() {
170                return tableHandlers;
171        }
172
173        public String getActionString(GuideUserAction action) throws MaltChainedException {
174                final StringBuilder sb = new StringBuilder();
175                action.getAction(actionContainers);
176                Table ttable = transitionTableHandler.getSymbolTable("TRANS");
177                sb.append(ttable.getSymbolCodeToString(transActionContainer.getActionCode()));
178                for (int i = 0; i < arcLabelActionContainers.length; i++) {
179                        if (arcLabelActionContainers[i].getActionCode() != -1) {
180                                sb.append("+");
181                                sb.append(arcLabelActionContainers[i].getTable().getSymbolCodeToString(arcLabelActionContainers[i].getActionCode()));
182                        }
183                }
184                return sb.toString();
185        }
186}