001package org.maltparser.parser.history;
002
003import java.util.ArrayList;
004
005import org.maltparser.core.exception.MaltChainedException;
006import org.maltparser.core.helper.HashMap;
007import org.maltparser.core.pool.ObjectPoolList;
008import org.maltparser.core.symbol.TableHandler;
009import org.maltparser.parser.history.action.ActionDecision;
010import org.maltparser.parser.history.action.ComplexDecisionAction;
011import org.maltparser.parser.history.action.GuideDecision;
012import org.maltparser.parser.history.action.GuideUserAction;
013import org.maltparser.parser.history.container.ActionContainer;
014import org.maltparser.parser.history.container.CombinedTableContainer;
015import org.maltparser.parser.history.container.TableContainer;
016
017/**
018*
019* @author Johan Hall
020**/
021public class History implements GuideUserHistory { 
022        private final ObjectPoolList<ComplexDecisionAction> actionPool;
023        private final int kBestSize;
024        private final String separator;
025        private final String decisionSettings;
026        private final ArrayList<TableContainer> decisionTables;
027        private final ArrayList<TableContainer> actionTables; 
028        private final HashMap<String, TableHandler> tableHandlers;
029        
030        public History(String _decisionSettings, String _separator, HashMap<String, TableHandler> _tableHandlers, int _kBestSize) throws MaltChainedException {
031                this.tableHandlers = _tableHandlers;
032                if (_separator == null || _separator.length() < 1) {
033                        this.separator = "~";
034                } else {
035                        this.separator = _separator;
036                }
037                this.kBestSize = _kBestSize;
038                this.decisionTables = new ArrayList<TableContainer>();
039                this.actionTables = new ArrayList<TableContainer>();
040                this.decisionSettings = _decisionSettings;
041                initDecisionSettings();
042                actionPool = new ObjectPoolList<ComplexDecisionAction>() {
043                        protected ComplexDecisionAction create() throws MaltChainedException { return new ComplexDecisionAction(getThis()); }
044                        public void resetObject(ComplexDecisionAction o) throws MaltChainedException { o.clear(); }
045                };
046                clear();
047        }
048        
049        private History getThis() {
050                return this;
051        }
052        
053        /* GuideUserHistory interface */
054        public GuideUserAction getEmptyGuideUserAction() throws MaltChainedException {
055                return (GuideUserAction)getEmptyActionObject();
056        }
057        
058        public ArrayList<ActionContainer> getActionContainers() {
059                ArrayList<ActionContainer> actionContainers = new ArrayList<ActionContainer>();
060                for (int i=0; i<actionTables.size(); i++) {
061                        actionContainers.add(new ActionContainer(actionTables.get(i)));
062                }
063                return actionContainers;
064        }
065        
066        public ActionContainer[] getActionContainerArray() {
067                ActionContainer[] actionContainers = new ActionContainer[actionTables.size()];
068                for (int i=0; i<actionTables.size(); i++) {
069                        actionContainers[i] = new ActionContainer(actionTables.get(i));
070                }
071                return actionContainers;
072        }
073        
074        
075        public void clear() throws MaltChainedException {
076                actionPool.checkInAll();
077        }
078        
079        /* GuideHistory interface */
080        public GuideDecision getEmptyGuideDecision() throws MaltChainedException {
081                return (GuideDecision)getEmptyActionObject();
082        }
083        
084        public int getNumberOfDecisions() {
085                return decisionTables.size();
086        }
087        
088        public TableHandler getTableHandler(String name) {
089                return tableHandlers.get(name);
090        }
091        
092        public int getKBestSize() {
093                return kBestSize;
094        }
095
096        public int getNumberOfActions() {
097                return actionTables.size();
098        }
099        
100        public ArrayList<TableContainer> getDecisionTables() {
101                return decisionTables;
102        }
103
104        public ArrayList<TableContainer> getActionTables() {
105                return actionTables;
106        }
107
108        public HashMap<String, TableHandler> getTableHandlers() {
109                return tableHandlers;
110        }
111        
112        public String getSeparator() {
113                return separator;
114        }
115
116        public String getDecisionSettings() {
117                return decisionSettings;
118        }
119        
120        private ActionDecision getEmptyActionObject() throws MaltChainedException {
121                return actionPool.checkOut();
122        }
123        
124        private void initDecisionSettings() throws MaltChainedException {
125                int start = 0;
126                int k = 0;
127                char prevDecisionSeparator = ' ';
128                TableContainer tmp = null;
129                final StringBuilder sbTableHandler = new StringBuilder();
130                final StringBuilder sbTable = new StringBuilder();
131                int state = 0;
132                for (int i = 0; i < decisionSettings.length(); i++) {
133                        switch (decisionSettings.charAt(i)) {
134                        case '.':
135                                state = 1;
136                                break;
137                        case '+':
138                                tmp = new TableContainer(tableHandlers.get(sbTableHandler.toString()).getSymbolTable(sbTable.toString()), 
139                                                sbTableHandler.toString()+"."+sbTable.toString(), '+');
140                                actionTables.add(tmp);
141                                k++;
142                                sbTableHandler.setLength(0);
143                                sbTable.setLength(0);
144                                state = 0;
145                                break;
146                        case '#':
147                                state = 2;
148                                break;
149                        case ';':
150                                state = 2;
151                                break;
152                        case ',':
153                                state = 2;
154                                break;
155                        default:
156                                if (state == 0) {
157                                        sbTableHandler.append(decisionSettings.charAt(i));
158                                } else if (state == 1) {
159                                        sbTable.append(decisionSettings.charAt(i));
160                                }
161                        }
162                        if (state == 2 || i == decisionSettings.length()-1) {
163                                char decisionSeparator = decisionSettings.charAt(i);
164                                if (i == decisionSettings.length()-1) {
165                                        decisionSeparator = prevDecisionSeparator;
166                                }
167                                tmp = new TableContainer(tableHandlers.get(sbTableHandler.toString()).getSymbolTable(sbTable.toString()), 
168                                                sbTableHandler.toString()+"."+sbTable.toString(), decisionSeparator);
169                                actionTables.add(tmp);
170                                k++;
171                                if (k-start > 1) {
172                                        decisionTables.add(new CombinedTableContainer(getTableHandler("A"), separator, actionTables.subList(start, k), decisionSeparator));
173                                } else {
174                                        decisionTables.add(tmp);
175                                }
176                                sbTableHandler.setLength(0);
177                                sbTable.setLength(0);
178                                state = 0;
179                                start = k;
180                                prevDecisionSeparator = decisionSeparator;
181                        }
182                }
183        }
184        
185        public String toString() {
186                StringBuilder sb = new StringBuilder();
187                return sb.toString();
188        }
189}