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