001    package org.maltparser.parser;
002    
003    import java.io.BufferedWriter;
004    import java.io.FileWriter;
005    import java.io.IOException;
006    import java.io.OutputStreamWriter;
007    import java.lang.reflect.Constructor;
008    import java.lang.reflect.InvocationTargetException;
009    
010    import org.maltparser.core.config.ConfigurationException;
011    import org.maltparser.core.exception.MaltChainedException;
012    import org.maltparser.core.symbol.SymbolTable;
013    import org.maltparser.core.syntaxgraph.DependencyStructure;
014    import org.maltparser.core.syntaxgraph.edge.Edge;
015    import org.maltparser.core.syntaxgraph.node.DependencyNode;
016    import org.maltparser.parser.guide.ClassifierGuide;
017    /**
018     * @author Johan Hall
019     *
020     */
021    public abstract class Algorithm {
022            protected DependencyParserConfig manager;
023            protected ClassifierGuide classifierGuide;
024            protected ParserState parserState;
025            protected ParserConfiguration currentParserConfiguration;
026            protected boolean diagnostics = false;
027            protected BufferedWriter diaWriter;
028            /**
029             * Creates a parsing algorithm
030             * 
031             * @param manager a reference to the single malt configuration
032             * @throws MaltChainedException
033             */
034            public Algorithm(DependencyParserConfig manager) throws MaltChainedException {
035                    setManager(manager);
036                    setDiagnostics((Boolean)manager.getOptionValue("singlemalt", "diagnostics"));
037                    if (diagnostics) {
038                            openDiaWriter(manager.getOptionValue("singlemalt", "diafile").toString());
039                    }
040            }
041            
042            public abstract void terminate() throws MaltChainedException;
043            
044            public boolean isDiagnostics() {
045                    return diagnostics;
046            }
047    
048            public void setDiagnostics(boolean diagnostics) {
049                    this.diagnostics = diagnostics;
050            }
051    
052    
053            public BufferedWriter getDiaWriter() {
054                    return diaWriter;
055            }
056            
057            public void writeToDiaFile(String message) throws MaltChainedException {
058                    try {
059                            getDiaWriter().write(message);
060                    } catch (IOException e) {
061                            throw new MaltChainedException("Could not write to the diagnostic file. ", e);
062                    }
063            }
064            
065            public void closeDiaWriter() throws MaltChainedException {
066                    if (diaWriter != null) {
067                            try {
068                                    diaWriter.flush();
069                                    diaWriter.close();
070                            } catch (IOException e) {
071                                    throw new MaltChainedException("Could not close the diagnostic file. ", e);
072                            }
073                    }
074            }
075            
076            public void openDiaWriter(String fileName) throws MaltChainedException {
077                    if (diagnostics) {
078                            try {
079                                    if (fileName.equals("stdout")) {
080                                            diaWriter = new BufferedWriter(new OutputStreamWriter(System.out));
081                                    } else if (fileName.equals("stderr")) {
082                                            diaWriter = new BufferedWriter(new OutputStreamWriter(System.err));
083                                    } else {
084                                            diaWriter = new BufferedWriter(new FileWriter(fileName));
085                                    }
086                            } catch (IOException e) {
087                                    throw new MaltChainedException("Could not open the diagnostic file. ", e);
088                            }
089                    }
090            }
091    
092            /**
093             * Returns the classifier guide.
094             * 
095             * @return the classifier guide
096             */
097            public ClassifierGuide getGuide() {
098                    return classifierGuide;
099            }
100            
101            /**
102             * Sets the classifier guide
103             * 
104             * @param guide a classifier guide
105             */
106            public void setGuide(ClassifierGuide guide) {
107                    this.classifierGuide = guide;
108            }
109    
110            /**
111             * Returns the current active parser configuration
112             * 
113             * @return the current active parser configuration
114             */
115            public ParserConfiguration getCurrentParserConfiguration() {
116                    return currentParserConfiguration;
117            }
118            
119            /**
120             * Sets the current parser configuration
121             * 
122             * @param currentParserConfiguration a parser configuration
123             */
124            protected void setCurrentParserConfiguration(ParserConfiguration currentParserConfiguration) {
125                    this.currentParserConfiguration = currentParserConfiguration;
126            }
127            
128            /**
129             * Returns the parser state
130             * 
131             * @return the parser state
132             */
133            public ParserState getParserState() {
134                    return parserState;
135            }
136            
137            /**
138             * Sets the parser state
139             * 
140             * @param parserState a parser state
141             */
142            protected void setParserState(ParserState parserState) {
143                    this.parserState = parserState;
144            }
145    
146            /**
147             * Creates a parser factory specified by the --singlemalt-parsing_algorithm option
148             * 
149             * @return a parser factory
150             * @throws MaltChainedException
151             */
152            protected AbstractParserFactory makeParserFactory() throws MaltChainedException {
153                    Class<?> clazz = (Class<?>)manager.getOptionValue("singlemalt", "parsing_algorithm");
154                    try {   
155                            Class<?>[] params = new Class<?>[1];
156                            params[0] = org.maltparser.parser.Algorithm.class;
157                            Object[] arguments = new Object[params.length];
158                            arguments[0] = this;
159                            Constructor<?> constructor = clazz.getConstructor(params);
160                            return (AbstractParserFactory)constructor.newInstance(arguments);
161                    } catch (NoSuchMethodException e) {
162                            throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e);
163                    } catch (InstantiationException e) {
164                            throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e);
165                    } catch (IllegalAccessException e) {
166                            throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e);
167                    } catch (InvocationTargetException e) {
168                            throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e);                        
169                    }
170            }
171            
172            protected void initParserState(int k) throws MaltChainedException {
173                    AbstractParserFactory parserFactory = makeParserFactory();
174                    ((SingleMalt)manager).addRegistry(parserFactory.getClass(), parserFactory);
175                    parserState = new ParserState(this, parserFactory, k);
176            }
177            
178            /**
179             * Returns the single malt configuration
180             * 
181             * @return the single malt configuration
182             */
183            public DependencyParserConfig getManager() {
184                    return manager;
185            }
186    
187            /**
188             * Sets the single malt configuration
189             * 
190             * @param manager a single malt configuration
191             */
192            public void setManager(DependencyParserConfig manager) {
193                    this.manager = manager;
194            }
195            
196            /**
197             * Copies the edges of the source dependency structure to the target dependency structure
198             * 
199             * @param source a source dependency structure
200             * @param target a target dependency structure
201             * @throws MaltChainedException
202             */
203            protected void copyEdges(DependencyStructure source, DependencyStructure target) throws MaltChainedException {
204                    for (int index : source.getTokenIndices()) {
205                            DependencyNode snode = source.getTokenNode(index);
206                            
207                            if (snode.hasHead()) {
208                                    Edge s = snode.getHeadEdge();
209                                    Edge t = target.addDependencyEdge(s.getSource().getIndex(), s.getTarget().getIndex());
210                                    
211                                    for (SymbolTable table : s.getLabelTypes()) {
212                                            t.addLabel(table, s.getLabelSymbol(table));
213                                    }
214                            }
215                    }
216            }
217            
218            protected void copyDynamicInput(DependencyStructure source, DependencyStructure target) throws MaltChainedException {
219                    for (int index : source.getTokenIndices()) {
220                            DependencyNode snode = source.getTokenNode(index);
221                            DependencyNode tnode = target.getTokenNode(index);
222                            for (SymbolTable table : snode.getLabelTypes()) {
223                                    if (!tnode.hasLabel(table)) {
224                                            tnode.addLabel(table,snode.getLabelSymbol(table));
225                                    }
226                            }
227                    }
228            }
229    }