001    package org.maltparser.parser.history;
002    
003    import java.util.ArrayList;
004    import java.util.HashMap;
005    
006    import org.maltparser.core.exception.MaltChainedException;
007    import org.maltparser.core.symbol.TableHandler;
008    import org.maltparser.parser.history.action.ActionDecision;
009    import org.maltparser.parser.history.action.ComplexDecisionAction;
010    import org.maltparser.parser.history.action.GuideDecision;
011    import org.maltparser.parser.history.action.GuideUserAction;
012    import org.maltparser.parser.history.container.ActionContainer;
013    import org.maltparser.parser.history.container.CombinedTableContainer;
014    import org.maltparser.parser.history.container.TableContainer;
015    import org.maltparser.parser.history.kbest.KBestList;
016    
017    /**
018    *
019    * @author Johan Hall
020    * @since 1.1
021    **/
022    public class History implements GuideUserHistory, GuideHistory {
023            protected ArrayList<ActionDecision> history;
024            protected int currentAction;
025            protected Class<? extends KBestList> kBestListClass = null;
026            protected int kBestSize;
027            protected String separator = "~";
028            protected String decisionSettings;
029            protected ArrayList<TableContainer> decisionTables;
030            protected ArrayList<TableContainer> actionTables; 
031            protected HashMap<String, TableHandler> tableHandlers;
032            
033            public History(String decisionSettings, String separator, HashMap<String, TableHandler> tableHandlers) throws MaltChainedException {
034                    setTableHandlers(tableHandlers);
035                    setSeparator(separator);
036                    initDecisionSettings(decisionSettings);
037                    history = new ArrayList<ActionDecision>();
038                    clear();
039            }
040            
041            /* GuideUserHistory interface */
042            public GuideUserAction getEmptyGuideUserAction() throws MaltChainedException {
043                    return (GuideUserAction)getEmptyActionObject();
044            }
045            
046            public ArrayList<ActionContainer> getActionContainers() {
047                    ArrayList<ActionContainer> actionContainers = new ArrayList<ActionContainer>();
048                    for (int i=0; i<actionTables.size(); i++) {
049                            actionContainers.add(new ActionContainer(actionTables.get(i)));
050                    }
051                    return actionContainers;
052            }
053            
054            public void clear() {
055                    currentAction = -1;
056            }
057            
058            /* GuideHistory interface */
059            public GuideDecision getEmptyGuideDecision() throws MaltChainedException {
060                    return (GuideDecision)getEmptyActionObject();
061            }
062            
063            public int getNumberOfDecisions() {
064                    return decisionTables.size();
065            }
066            
067            public TableHandler getTableHandler(String name) {
068                    return tableHandlers.get(name);
069            }
070    
071            public Class<? extends KBestList> getKBestListClass() {
072                    return kBestListClass;
073            }
074            
075            public void setKBestListClass(Class<?> kBestListClass) throws MaltChainedException {
076                    try {
077                            if (kBestListClass != null) {
078                                    this.kBestListClass = kBestListClass.asSubclass(org.maltparser.parser.history.kbest.KBestList.class);
079                            }
080                    } catch (ClassCastException e) {
081                            throw new HistoryException("The class '"+kBestListClass.getName()+"' is not a subclass of '"+org.maltparser.parser.history.kbest.KBestList.class.getName()+"'. ", e);
082                    }
083            }
084            
085            public int getKBestSize() {
086                    return kBestSize;
087            }
088    
089            public void setKBestSize(int kBestSize) {
090                    this.kBestSize = kBestSize;
091            }
092    
093            public int getNumberOfActions() {
094                    return actionTables.size();
095            }
096            
097            public ArrayList<TableContainer> getDecisionTables() {
098                    return decisionTables;
099            }
100    
101            public ArrayList<TableContainer> getActionTables() {
102                    return actionTables;
103            }
104    
105            public HashMap<String, TableHandler> getTableHandlers() {
106                    return tableHandlers;
107            }
108            
109            public String getSeparator() {
110                    return separator;
111            }
112    
113            public void setSeparator(String separator) throws MaltChainedException {
114                    if (separator == null || separator.length() < 1) {
115                            throw new HistoryException("The class item separator (--guide-classitem_separator) does not have correct value. ");
116                    }
117                    this.separator = separator;
118            }
119    
120            public String getDecisionSettings() {
121                    return decisionSettings;
122            }
123    
124            public void setDecisionSettings(String decisionSettings) {
125                    this.decisionSettings = decisionSettings;
126            }
127    
128            protected void setTableHandlers(HashMap<String, TableHandler> tableHandlers) {
129                    this.tableHandlers = tableHandlers;
130            }
131            
132            protected ActionDecision getEmptyActionObject() throws MaltChainedException {
133                    ActionDecision actionObject = null;
134                    if (currentAction + 1 >= history.size()) {
135                            actionObject = new ComplexDecisionAction(this);
136                    } else {
137                            actionObject = history.get(++currentAction);
138                            actionObject.clear();
139                    }
140                    return actionObject;
141            }
142            
143            protected void initDecisionSettings(String decisionSettings) throws MaltChainedException {
144                    decisionTables = new ArrayList<TableContainer>();
145                    actionTables = new ArrayList<TableContainer>();
146                    this.decisionSettings = decisionSettings;
147                    int start = 0;
148                    int k = 0;
149                    char prevDecisionSeparator = ' ';
150                    TableContainer tmp = null;
151                    final StringBuilder sbTableHandler = new StringBuilder();
152                    final StringBuilder sbTable = new StringBuilder();
153                    int state = 0;
154                    for (int i = 0; i < decisionSettings.length(); i++) {
155                            switch (decisionSettings.charAt(i)) {
156                            case '.':
157                                    if (state != 0) {
158                                            //error
159                                    }
160                                    state = 1;
161                                    break;
162                            case '+':
163                                    tmp = new TableContainer(tableHandlers.get(sbTableHandler.toString()).getSymbolTable(sbTable.toString()), sbTableHandler.toString()+"."+sbTable.toString(), '+');
164                                    actionTables.add(tmp);
165                                    k++;
166                                    sbTableHandler.setLength(0);
167                                    sbTable.setLength(0);
168                                    state = 0;
169                                    break;
170                            case '#':
171                                    state = 2;
172                                    break;
173                            case ';':
174                                    state = 2;
175                                    break;
176                            case ',':
177                                    state = 2;
178                                    break;
179                            default:
180                                    if (state == 0) {
181                                            sbTableHandler.append(decisionSettings.charAt(i));
182                                    } else if (state == 1) {
183                                            sbTable.append(decisionSettings.charAt(i));
184                                    }
185                            }
186                            if (state == 2 || i == decisionSettings.length()-1) {
187                                    char decisionSeparator = decisionSettings.charAt(i);
188                                    if (i == decisionSettings.length()-1) {
189                                            //decisionSeparator = ' ';
190                                            decisionSeparator = prevDecisionSeparator;
191                                    }
192                                    tmp = new TableContainer(tableHandlers.get(sbTableHandler.toString()).getSymbolTable(sbTable.toString()), sbTableHandler.toString()+"."+sbTable.toString(), decisionSeparator);
193                                    actionTables.add(tmp);
194                                    k++;
195                                    if (k-start > 1) {
196                                            decisionTables.add(new CombinedTableContainer(getTableHandler("A"), separator, actionTables.subList(start, k), decisionSeparator));
197                                    } else {
198                                            decisionTables.add(tmp);
199                                    }
200                                    sbTableHandler.setLength(0);
201                                    sbTable.setLength(0);
202                                    state = 0;
203                                    start = k;
204                                    prevDecisionSeparator = decisionSeparator;
205                            }
206                    }
207            }
208            
209            public String toString() {
210                    StringBuilder sb = new StringBuilder();
211                    
212                    for (int i = 0; i <= currentAction; i++) {
213                            sb.append(history.get(i));
214                    }
215                    return sb.toString();
216            }
217    }