001    package org.maltparser.core.config;
002    
003    import java.io.BufferedInputStream;
004    import java.io.BufferedOutputStream;
005    import java.io.BufferedReader;
006    import java.io.BufferedWriter;
007    import java.io.File;
008    import java.io.FileInputStream;
009    import java.io.FileNotFoundException;
010    import java.io.FileOutputStream;
011    import java.io.FileReader;
012    import java.io.FileWriter;
013    import java.io.IOException;
014    import java.io.InputStream;
015    import java.io.InputStreamReader;
016    import java.io.OutputStreamWriter;
017    import java.io.UnsupportedEncodingException;
018    import java.net.MalformedURLException;
019    import java.net.URL;
020    import java.util.Date;
021    import java.util.Enumeration;
022    import java.util.HashMap;
023    import java.util.Set;
024    import java.util.SortedSet;
025    import java.util.TreeSet;
026    import java.util.jar.JarEntry;
027    import java.util.jar.JarFile;
028    import java.util.jar.JarInputStream;
029    import java.util.jar.JarOutputStream;
030    
031    import org.maltparser.core.config.version.Versioning;
032    import org.maltparser.core.exception.MaltChainedException;
033    import org.maltparser.core.helper.HashSet;
034    import org.maltparser.core.helper.SystemInfo;
035    import org.maltparser.core.helper.SystemLogger;
036    import org.maltparser.core.helper.URLFinder;
037    import org.maltparser.core.io.dataformat.DataFormatInstance;
038    import org.maltparser.core.io.dataformat.DataFormatManager;
039    import org.maltparser.core.io.dataformat.DataFormatSpecification.DataStructure;
040    import org.maltparser.core.io.dataformat.DataFormatSpecification.Dependency;
041    import org.maltparser.core.options.OptionManager;
042    import org.maltparser.core.symbol.SymbolTableHandler;
043    import org.maltparser.core.symbol.trie.TrieSymbolTableHandler;
044    
045    
046    /**
047    * This class contains methods for handle the configuration directory.
048    *
049    * @author Johan Hall
050    */
051    public class ConfigurationDir  {
052            protected static final int BUFFER = 4096;
053            protected File configDirectory;
054            protected String name;
055            protected String type;
056            protected File workingDirectory;
057            protected URL url = null;
058            protected int containerIndex;
059            protected BufferedWriter infoFile = null;
060            protected String createdByMaltParserVersion;
061    
062            private SymbolTableHandler symbolTables;
063            private DataFormatManager dataFormatManager;
064            private HashMap<String,DataFormatInstance> dataFormatInstances;
065            private URL inputFormatURL; 
066            private URL outputFormatURL; 
067            
068            /**
069             * Creates a configuration directory from a mco-file specified by an URL.
070             * 
071             * @param url   an URL to a mco-file
072             * @throws MaltChainedException
073             */
074            public ConfigurationDir(URL url) throws MaltChainedException {
075                    initWorkingDirectory();
076                    setUrl(url);
077                    initNameNTypeFromInfoFile(url);
078    //              initData();
079            }
080            
081            /**
082             * Creates a new configuration directory or a configuration directory from a mco-file
083             * 
084             * @param name  the name of the configuration
085             * @param type  the type of configuration
086             * @param containerIndex        the container index
087             * @throws MaltChainedException
088             */
089            public ConfigurationDir(String name, String type, int containerIndex) throws MaltChainedException {
090                    setContainerIndex(containerIndex);
091    
092                    initWorkingDirectory();
093                    if (name != null && name.length() > 0 && type != null && type.length() > 0) {
094                            setName(name);
095                            setType(type);
096                    } else {
097                            throw new ConfigurationException("The configuration name is not specified. ");
098                    }
099                    setConfigDirectory(new File(workingDirectory.getPath()+File.separator+getName()));
100            }
101            
102            public void initDataFormat() throws MaltChainedException {
103                    String inputFormatName = OptionManager.instance().getOptionValue(containerIndex, "input", "format").toString().trim();
104                    String outputFormatName = OptionManager.instance().getOptionValue(containerIndex, "output", "format").toString().trim();
105                    final URLFinder f = new URLFinder();
106    
107                    if (configDirectory != null && configDirectory.exists()) {
108                            if (outputFormatName.length() == 0 || inputFormatName.equals(outputFormatName)) {
109                                    URL inputFormatURL = f.findURLinJars(inputFormatName);
110                                    if (inputFormatURL != null) {
111                                            outputFormatName = inputFormatName = this.copyToConfig(inputFormatURL);
112                                    } else {
113                                            outputFormatName = inputFormatName = this.copyToConfig(inputFormatName);
114                                    }
115                            } else {
116                                    URL inputFormatURL = f.findURLinJars(inputFormatName);
117                                    if (inputFormatURL != null) {
118                                            inputFormatName = this.copyToConfig(inputFormatURL);
119                                    } else {
120                                            inputFormatName = this.copyToConfig(inputFormatName);
121                                    }
122                                    URL outputFormatURL = f.findURLinJars(outputFormatName);
123                                    if (inputFormatURL != null) {
124                                            outputFormatName = this.copyToConfig(outputFormatURL);
125                                    } else {
126                                            outputFormatName = this.copyToConfig(outputFormatName);
127                                    }
128                            }
129                            OptionManager.instance().overloadOptionValue(containerIndex, "input", "format", inputFormatName);
130                    } else {
131                            if (outputFormatName.length() == 0) {
132                                    outputFormatName = inputFormatName;
133                            }
134                    }
135                    dataFormatInstances = new HashMap<String, DataFormatInstance>(3);
136    
137                    inputFormatURL = findURL(inputFormatName);
138                    outputFormatURL = findURL(outputFormatName);
139                    if (outputFormatURL != null) {
140                            try {
141                                    InputStream is = outputFormatURL.openStream();
142                            } catch (FileNotFoundException e) {
143                                    outputFormatURL = f.findURL(outputFormatName);
144                            } catch (IOException e) {
145                                    outputFormatURL = f.findURL(outputFormatName);
146                            }
147                    } else {
148                            outputFormatURL = f.findURL(outputFormatName);
149                    }
150                    dataFormatManager = new DataFormatManager(inputFormatURL, outputFormatURL);
151                    
152                    String mode = OptionManager.instance().getOptionValue(containerIndex, "config", "flowchart").toString().trim();
153                    if (mode.equals("parse")) {
154                            symbolTables = new TrieSymbolTableHandler(TrieSymbolTableHandler.ADD_NEW_TO_TMP_STORAGE);
155    //                      symbolTables = new TrieSymbolTableHandler(TrieSymbolTableHandler.ADD_NEW_TO_TRIE);
156                    } else {
157                            symbolTables = new TrieSymbolTableHandler(TrieSymbolTableHandler.ADD_NEW_TO_TRIE);
158                    }
159                    if (dataFormatManager.getInputDataFormatSpec().getDataStructure() == DataStructure.PHRASE) {
160                            if (mode.equals("learn")) {
161                                    Set<Dependency> deps = dataFormatManager.getInputDataFormatSpec().getDependencies();
162                                    for (Dependency dep : deps) {
163                                            URL depFormatURL = f.findURLinJars(dep.getUrlString());
164                                            if (depFormatURL != null) {
165                                                    this.copyToConfig(depFormatURL);
166                                            } else {
167                                                    this.copyToConfig(dep.getUrlString());
168                                            }
169                                    }
170                            } 
171                            else if (mode.equals("parse")) {
172                                    Set<Dependency> deps = dataFormatManager.getInputDataFormatSpec().getDependencies();
173                                    String nullValueStategy = OptionManager.instance().getOptionValue(containerIndex, "singlemalt", "null_value").toString();
174                                    for (Dependency dep : deps) {
175    //                                      URL depFormatURL = f.findURLinJars(dep.getUrlString());
176                                            DataFormatInstance dataFormatInstance = dataFormatManager.getDataFormatSpec(dep.getDependentOn()).createDataFormatInstance(symbolTables, nullValueStategy);
177                                            addDataFormatInstance(dataFormatManager.getDataFormatSpec(dep.getDependentOn()).getDataFormatName(), dataFormatInstance);
178                                            dataFormatManager.setInputDataFormatSpec(dataFormatManager.getDataFormatSpec(dep.getDependentOn()));
179    //                                      dataFormatManager.setOutputDataFormatSpec(dataFormatManager.getDataFormatSpec(dep.getDependentOn()));
180                                    }
181                            }
182                    }
183            }
184            
185            private URL findURL(String specModelFileName) throws MaltChainedException {
186                    URL url = null;
187                    File specFile = this.getFile(specModelFileName);
188                    if (specFile.exists()) {
189                            try {
190                                    url = new URL("file:///"+specFile.getAbsolutePath());
191                            } catch (MalformedURLException e) {
192                                    throw new MaltChainedException("Malformed URL: "+specFile, e);
193                            }
194                    } else {
195                            url = this.getConfigFileEntryURL(specModelFileName);
196                    }
197                    return url;
198            }
199            
200            /**
201             * Creates an output stream writer, where the corresponding file will be included in the configuration directory
202             * 
203             * @param fileName      a file name
204             * @param charSet       a char set
205             * @return      an output stream writer for writing to a file within the configuration directory
206             * @throws MaltChainedException
207             */
208            public OutputStreamWriter getOutputStreamWriter(String fileName, String charSet) throws MaltChainedException {
209                    try {
210                            return new OutputStreamWriter(new FileOutputStream(configDirectory.getPath()+File.separator+fileName), charSet);
211                    } catch (FileNotFoundException e) {
212                            throw new ConfigurationException("The file '"+fileName+"' cannot be created. ", e);
213                    } catch (UnsupportedEncodingException e) {
214                            throw new ConfigurationException("The char set '"+charSet+"' is not supported. ", e);
215                    }
216            }
217            
218            /**
219             * Creates an output stream writer, where the corresponding file will be included in the 
220             * configuration directory. Uses UTF-8 for character encoding.
221             * 
222             * @param fileName      a file name
223             * @return an output stream writer for writing to a file within the configuration directory
224             * @throws MaltChainedException
225             */
226            public OutputStreamWriter getOutputStreamWriter(String fileName) throws MaltChainedException {
227                    try {
228                            return new OutputStreamWriter(new FileOutputStream(configDirectory.getPath()+File.separator+fileName, true), "UTF-8");
229                    } catch (FileNotFoundException e) {
230                            throw new ConfigurationException("The file '"+fileName+"' cannot be created. ", e);
231                    } catch (UnsupportedEncodingException e) {
232                            throw new ConfigurationException("The char set 'UTF-8' is not supported. ", e);
233                    }
234            }
235            /**
236             * This method acts the same as getOutputStreamWriter with the difference that the writer append in the file
237             * if it already exists instead of deleting the previous content before starting to write.
238             * 
239             * @param fileName      a file name
240             * @return an output stream writer for writing to a file within the configuration directory
241             * @throws MaltChainedException
242             */
243            public OutputStreamWriter getAppendOutputStreamWriter(String fileName) throws MaltChainedException {
244                    try {
245                            return new OutputStreamWriter(new FileOutputStream(configDirectory.getPath()+File.separator+fileName, true), "UTF-8");
246                    } catch (FileNotFoundException e) {
247                            throw new ConfigurationException("The file '"+fileName+"' cannot be created. ", e);
248                    } catch (UnsupportedEncodingException e) {
249                            throw new ConfigurationException("The char set 'UTF-8' is not supported. ", e);
250                    }
251            }
252            
253            /**
254             * Creates an input stream reader for reading a file within the configuration directory
255             * 
256             * @param fileName      a file name
257             * @param charSet       a char set
258             * @return an input stream reader for reading a file within the configuration directory
259             * @throws MaltChainedException
260             */
261            public InputStreamReader getInputStreamReader(String fileName, String charSet) throws MaltChainedException {
262                    try {
263                            return new InputStreamReader(new FileInputStream(configDirectory.getPath()+File.separator+fileName), charSet);
264                    } catch (FileNotFoundException e) {
265                            throw new ConfigurationException("The file '"+fileName+"' cannot be found. ", e);
266                    } catch (UnsupportedEncodingException e) {
267                            throw new ConfigurationException("The char set '"+charSet+"' is not supported. ", e);
268                    }
269            }
270            
271            /**
272             * Creates an input stream reader for reading a file within the configuration directory.
273             * Uses UTF-8 for character encoding.
274             * 
275             * @param fileName      a file name
276             * @return      an input stream reader for reading a file within the configuration directory
277             * @throws MaltChainedException
278             */
279            public InputStreamReader getInputStreamReader(String fileName) throws MaltChainedException {
280                    return getInputStreamReader(fileName, "UTF-8");
281            }
282            
283            public JarEntry getConfigFileEntry(String fileName) throws MaltChainedException {
284                    File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
285                    try {
286                            JarFile mcoFile = new JarFile(mcoPath.getAbsolutePath());
287                            JarEntry entry = mcoFile.getJarEntry(getName()+'/'+fileName);
288                            if (entry == null) {
289                                    entry = mcoFile.getJarEntry(getName()+'\\'+fileName);
290                            }
291                            return entry;
292                    } catch (FileNotFoundException e) {
293                            throw new ConfigurationException("The file entry '"+fileName+"' in mco-file '"+mcoPath+"' cannot be found. ", e);
294                    } catch (IOException e) {
295                            throw new ConfigurationException("The file entry '"+fileName+"' in mco-file '"+mcoPath+"' cannot be found. ", e);
296                    }
297            }
298            
299            public InputStream getInputStreamFromConfigFileEntry(String fileName) throws MaltChainedException {
300                    File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
301                    try {
302                            JarFile mcoFile = new JarFile(mcoPath.getAbsolutePath());
303                            JarEntry entry = mcoFile.getJarEntry(getName()+'/'+fileName);
304                            if (entry == null) {
305                                    entry = mcoFile.getJarEntry(getName()+'\\'+fileName);
306                            }
307                            if (entry == null) {
308                                    throw new FileNotFoundException();
309                            }
310                            return mcoFile.getInputStream(entry);
311                    } catch (FileNotFoundException e) {
312                            throw new ConfigurationException("The file entry '"+fileName+"' in the mco file '"+mcoPath+"' cannot be found. ", e);
313                    } catch (IOException e) {
314                            throw new ConfigurationException("The file entry '"+fileName+"' in the mco file '"+mcoPath+"' cannot be loaded. ", e);
315                    }
316            }
317            
318            public InputStreamReader getInputStreamReaderFromConfigFileEntry(String fileName, String charSet) throws MaltChainedException {
319                    File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
320                    try {
321                            JarFile mcoFile = new JarFile(mcoPath.getAbsolutePath());
322                            JarEntry entry = mcoFile.getJarEntry(getName()+'/'+fileName);
323                            if (entry == null) {
324                                    entry = mcoFile.getJarEntry(getName()+'\\'+fileName);
325                            }
326                            if (entry == null) {
327                                    throw new FileNotFoundException();
328                            }
329                            return new InputStreamReader(mcoFile.getInputStream(entry),  charSet);
330                    } catch (FileNotFoundException e) {
331                            throw new ConfigurationException("The file entry '"+fileName+"' in the mco file '"+mcoPath+"' cannot be found. ", e);
332                    } catch (UnsupportedEncodingException e) {
333                            throw new ConfigurationException("The char set '"+charSet+"' is not supported. ", e);
334                    } catch (IOException e) {
335                            throw new ConfigurationException("The file entry '"+fileName+"' in the mco file '"+mcoPath+"' cannot be loaded. ", e);
336                    }
337            }
338            
339            public InputStreamReader getInputStreamReaderFromConfigFile(String fileName) throws MaltChainedException {
340                    return getInputStreamReaderFromConfigFileEntry(fileName, "UTF-8");
341            }
342            
343            /**
344             * Returns a file handler object of a file within the configuration directory
345             * 
346             * @param fileName      a file name
347             * @return      a file handler object of a file within the configuration directory
348             * @throws MaltChainedException
349             */
350            public File getFile(String fileName) throws MaltChainedException {
351                    return new File(configDirectory.getPath()+File.separator+fileName);
352            }
353            
354            public URL getConfigFileEntryURL(String fileName) throws MaltChainedException {
355                    File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
356                    try {
357                            if (!mcoPath.exists()) {
358                                    throw new ConfigurationException("Couldn't find mco-file '" +mcoPath.getAbsolutePath()+ "'");
359                            }
360    //                      new URL("file", null, mcoPath.getAbsolutePath());
361                            URL url = new URL("jar:"+new URL("file", null, mcoPath.getAbsolutePath())+"!/"+getName()+'/'+fileName + "\n");
362                            try { 
363                                    InputStream is = url.openStream();
364                                    is.close();
365                            } catch (IOException e) {
366                                    url = new URL("jar:"+new URL("file", null, mcoPath.getAbsolutePath())+"!/"+getName()+'\\'+fileName + "\n");
367                            }
368                            return url;
369                    } catch (MalformedURLException e) {
370                            throw new ConfigurationException("Couldn't find the URL '" +"jar:"+mcoPath.getAbsolutePath()+"!/"+getName()+'/'+fileName+ "'", e);
371                    }
372            }
373            
374        /**
375         * Copies a file into the configuration directory.
376         * 
377         * @param source    a path to file 
378         * @throws MaltChainedException
379         */
380        public String copyToConfig(File source) throws MaltChainedException {
381            byte[] readBuffer = new byte[BUFFER];
382            String destination = configDirectory.getPath()+File.separator+source.getName();
383            try {
384                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
385                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destination), BUFFER);
386                
387                    int n = 0;
388                        while ((n = bis.read(readBuffer, 0, BUFFER)) != -1) {
389                            bos.write(readBuffer, 0, n);
390                        }
391                    bos.flush();
392                    bos.close();
393                    bis.close();
394                    } catch (FileNotFoundException e) {
395                            throw new ConfigurationException("The source file '"+source+"' cannot be found or the destination file '"+destination+"' cannot be created when coping the file. ", e);
396                    } catch (IOException e) {
397                            throw new ConfigurationException("The source file '"+source+"' cannot be copied to destination '"+destination+"'. ", e);
398                    }
399                    return source.getName();
400        }
401        
402    
403        public String copyToConfig(String fileUrl) throws MaltChainedException {
404            final URLFinder f = new URLFinder();
405            URL url = f.findURL(fileUrl);
406            if (url == null) {
407                    throw new ConfigurationException("The file or URL '"+fileUrl+"' could not be found. ");
408            }
409            return copyToConfig(url);
410        }
411        
412        public String copyToConfig(URL url) throws MaltChainedException {
413            if (url == null) {
414                    throw new ConfigurationException("URL could not be found. ");
415            }
416            byte[] readBuffer = new byte[BUFFER];
417            String destFileName = url.getPath();
418                    int indexSlash = destFileName.lastIndexOf('/');
419                    if (indexSlash == -1) {
420                            indexSlash = destFileName.lastIndexOf('\\');
421                    }
422            
423                    if (indexSlash != -1) {
424                            destFileName = destFileName.substring(indexSlash+1);
425                    }
426            
427            String destination = configDirectory.getPath()+File.separator+destFileName;
428            try {
429                    BufferedInputStream bis = new BufferedInputStream(url.openStream());
430                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destination), BUFFER);
431                
432                    int n = 0;
433                        while ((n = bis.read(readBuffer, 0, BUFFER)) != -1) {
434                            bos.write(readBuffer, 0, n);
435                        }
436                    bos.flush();
437                    bos.close();
438                    bis.close();
439                    } catch (FileNotFoundException e) {
440                            throw new ConfigurationException("The destination file '"+destination+"' cannot be created when coping the file. ", e);
441                    } catch (IOException e) {
442                            throw new ConfigurationException("The URL '"+url+"' cannot be copied to destination '"+destination+"'. ", e);
443                    }
444                    return destFileName;
445        }
446     
447        
448            /**
449             * Removes the configuration directory, if it exists and it contains a .info file. 
450             * 
451             * @throws MaltChainedException
452             */
453            public void deleteConfigDirectory() throws MaltChainedException {
454                    if (!configDirectory.exists()) {
455                            return;
456                    }
457                    File infoFile = new File(configDirectory.getPath()+File.separator+getName()+"_"+getType()+".info");
458                    if (infoFile.exists()) {
459                            deleteConfigDirectory(configDirectory);
460                    } else {
461                            throw new ConfigurationException("There exists a directory that is not a MaltParser configuration directory. ");
462                    }
463            }
464            
465            private void deleteConfigDirectory(File directory) throws MaltChainedException {
466                    if (directory.exists()) {
467                            File[] files = directory.listFiles();
468                            for (int i = 0; i < files.length; i++) {
469                                    if (files[i].isDirectory()) {
470                                            deleteConfigDirectory(files[i]);
471                                    } else {
472                                            files[i].delete();
473                                    }
474                            }
475                    } else {
476                            throw new ConfigurationException("The directory '"+directory.getPath()+ "' cannot be found. ");
477                    }
478                    directory.delete();
479            }
480            
481            /**
482             * Returns a file handler object for the configuration directory
483             * 
484             * @return a file handler object for the configuration directory
485             */
486            public File getConfigDirectory() {
487                    return configDirectory;
488            }
489    
490            protected void setConfigDirectory(File dir) {
491                    this.configDirectory = dir;
492            }
493    
494            /**
495             * Creates the configuration directory
496             * 
497             * @throws MaltChainedException
498             */
499            public void createConfigDirectory() throws MaltChainedException {
500                    checkConfigDirectory();
501                    configDirectory.mkdir();
502                    createInfoFile();
503            }
504            
505            protected void checkConfigDirectory()  throws MaltChainedException {
506                    if (configDirectory.exists() && !configDirectory.isDirectory()) {
507                            throw new ConfigurationException("The configuration directory name already exists and is not a directory. ");
508                    }
509                    
510                    if (configDirectory.exists()) {
511                            deleteConfigDirectory();
512                    } 
513            }
514            
515            protected void createInfoFile() throws MaltChainedException {
516                    infoFile = new BufferedWriter(getOutputStreamWriter(getName()+"_"+getType()+".info"));
517                    try {
518                            infoFile.write("CONFIGURATION\n");
519                            infoFile.write("Configuration name:   "+getName()+"\n");
520                            infoFile.write("Configuration type:   "+getType()+"\n");
521                            infoFile.write("Created:              "+new Date(System.currentTimeMillis())+"\n");
522                            
523                            infoFile.write("\nSYSTEM\n");
524                            infoFile.write("Operating system architecture: "+System.getProperty("os.arch")+"\n");
525                            infoFile.write("Operating system name:         "+System.getProperty("os.name")+"\n");
526                            infoFile.write("JRE vendor name:               "+System.getProperty("java.vendor")+"\n");
527                            infoFile.write("JRE version number:            "+System.getProperty("java.version")+"\n");
528                            
529                            infoFile.write("\nMALTPARSER\n");
530                            infoFile.write("Version:                       "+SystemInfo.getVersion()+"\n");
531                            infoFile.write("Build date:                    "+SystemInfo.getBuildDate()+"\n");
532                            Set<String> excludeGroups = new HashSet<String>();
533                            excludeGroups.add("system");
534                            infoFile.write("\nSETTINGS\n");
535                            infoFile.write(OptionManager.instance().toStringPrettyValues(containerIndex, excludeGroups));
536                            infoFile.flush();
537                    } catch (IOException e) {
538                            throw new ConfigurationException("Could not create the maltparser info file. ");
539                    }
540            }
541            
542            /**
543             * Returns a writer to the configuration information file
544             * 
545             * @return      a writer to the configuration information file
546             * @throws MaltChainedException
547             */
548            public BufferedWriter getInfoFileWriter() throws MaltChainedException {
549                    return infoFile;
550            }
551            
552            /**
553             * Creates the malt configuration file (.mco). This file is compressed.   
554             * 
555             * @throws MaltChainedException
556             */
557            public void createConfigFile() throws MaltChainedException {
558                    try {
559                            JarOutputStream jos = new JarOutputStream(new FileOutputStream(workingDirectory.getPath()+File.separator+getName()+".mco"));
560    //                      configLogger.info("Creates configuration file '"+workingDirectory.getPath()+File.separator+getName()+".mco' ...\n");
561                            createConfigFile(configDirectory.getPath(), jos);
562                            jos.close();
563                    } catch (FileNotFoundException e) {
564                            throw new ConfigurationException("The maltparser configurtation file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be found. ", e);
565                    } catch (IOException e) {
566                            throw new ConfigurationException("The maltparser configurtation file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be created. ", e);
567                    } 
568            }
569    
570            private void createConfigFile(String directory, JarOutputStream jos) throws MaltChainedException {
571            byte[] readBuffer = new byte[BUFFER];
572                    try {
573                            File zipDir = new File(directory);
574                            String[] dirList = zipDir.list();
575                            
576                            int bytesIn = 0;
577            
578                            for (int i = 0; i < dirList.length; i++) {
579                                    File f = new File(zipDir, dirList[i]);
580                                    if (f.isDirectory()) {
581                                            String filePath = f.getPath();
582                                            createConfigFile(filePath, jos);
583                                            continue;
584                                    }
585            
586                                    FileInputStream fis = new FileInputStream(f);
587                                    
588                                    String entryPath = f.getPath().substring(workingDirectory.getPath().length()+1);
589                                    entryPath = entryPath.replace('\\', '/');
590                                    JarEntry entry = new JarEntry(entryPath);
591                                    jos.putNextEntry(entry);
592            
593                                    while ((bytesIn = fis.read(readBuffer)) != -1) {
594                                            jos.write(readBuffer, 0, bytesIn);
595                                    }
596            
597                                    fis.close();
598                            }
599                    } catch (FileNotFoundException e) {
600                            throw new ConfigurationException("The directory '"+directory+"' cannot be found. ", e);
601                    } catch (IOException e) {
602                            throw new ConfigurationException("The directory '"+directory+"' cannot be compressed into a mco file. ", e);
603                    } 
604            }
605            
606    
607            public void copyConfigFile(File in, File out, Versioning versioning) throws MaltChainedException {
608                    try {
609                            JarFile jar = new JarFile(in);
610                            JarOutputStream tempJar = new JarOutputStream(new FileOutputStream(out));
611                    byte[] buffer = new byte[BUFFER];
612                    int bytesRead;
613                    final StringBuilder sb = new StringBuilder();
614                    final URLFinder f = new URLFinder();
615    
616                    for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) {
617                        JarEntry inEntry = (JarEntry) entries.nextElement();
618                        InputStream entryStream = jar.getInputStream(inEntry);
619                        JarEntry outEntry = versioning.getJarEntry(inEntry);
620                        
621                        if (!versioning.hasChanges(inEntry, outEntry)) {
622                                tempJar.putNextEntry(outEntry);
623                                while ((bytesRead = entryStream.read(buffer)) != -1) {
624                                    tempJar.write(buffer, 0, bytesRead);
625                                }
626                        } else {
627                            tempJar.putNextEntry(outEntry);
628                            BufferedReader br = new BufferedReader(new InputStreamReader(entryStream));
629                            String line = null;
630                            sb.setLength(0);
631                            while ((line = br.readLine()) != null) {
632                                    sb.append(line);
633                                    sb.append('\n');
634                            }
635                            String outString = versioning.modifyJarEntry(inEntry, outEntry, sb);
636                            tempJar.write(outString.getBytes());
637                        }
638                    }
639                    if (versioning.getFeatureModelXML() != null && versioning.getFeatureModelXML().startsWith("/appdata")) {
640                            int index = versioning.getFeatureModelXML().lastIndexOf('/');
641                    BufferedInputStream bis = new BufferedInputStream(f.findURLinJars(versioning.getFeatureModelXML()).openStream());
642                    tempJar.putNextEntry(new JarEntry(versioning.getNewConfigName()+"/" +versioning.getFeatureModelXML().substring(index+1)));
643                    int n = 0;
644                        while ((n = bis.read(buffer, 0, BUFFER)) != -1) {
645                            tempJar.write(buffer, 0, n);
646                        }
647                    bis.close();
648                    }
649                    if (versioning.getInputFormatXML() != null && versioning.getInputFormatXML().startsWith("/appdata")) {
650                            int index = versioning.getInputFormatXML().lastIndexOf('/');
651                    BufferedInputStream bis = new BufferedInputStream(f.findURLinJars(versioning.getInputFormatXML()).openStream());
652                    tempJar.putNextEntry(new JarEntry(versioning.getNewConfigName()+"/" +versioning.getInputFormatXML().substring(index+1)));
653                    int n = 0;
654                        while ((n = bis.read(buffer, 0, BUFFER)) != -1) {
655                            tempJar.write(buffer, 0, n);
656                        }
657                    bis.close();
658                    }
659                    tempJar.flush();
660                    tempJar.close();
661                    jar.close();
662                    } catch (IOException e) {
663                            throw new ConfigurationException("", e);
664                    }
665            }
666            
667        protected void initNameNTypeFromInfoFile(URL url) throws MaltChainedException {
668                    if (url == null) {
669                            throw new ConfigurationException("The URL cannot be found. ");
670                    }       
671                    try {
672                            JarEntry je;
673                            JarInputStream jis = new JarInputStream(url.openConnection().getInputStream());
674                            while ((je = jis.getNextJarEntry()) != null) {
675                                    String entryName = je.getName();
676                                    if (entryName.endsWith(".info")) {
677                                            int indexUnderScore = entryName.lastIndexOf('_');
678                                            int indexSeparator = entryName.lastIndexOf(File.separator);
679                                            if (indexSeparator == -1) {
680                                                    indexSeparator = entryName.lastIndexOf('/');
681                                            }
682                                            if (indexSeparator == -1) {
683                                                    indexSeparator = entryName.lastIndexOf('\\');
684                                            }
685                                            int indexDot = entryName.lastIndexOf('.');
686                                            if (indexUnderScore == -1 || indexDot == -1) {
687                                                    throw new ConfigurationException("Could not find the configuration name and type from the URL '"+url.toString()+"'. ");
688                                            }
689                                            setName(entryName.substring(indexSeparator+1, indexUnderScore));
690                                            setType(entryName.substring(indexUnderScore+1, indexDot));
691                                            setConfigDirectory(new File(workingDirectory.getPath()+File.separator+getName()));
692                                            jis.close();
693                                            return;
694                                    }
695                            }
696                            
697                    } catch (IOException e) {
698                            throw new ConfigurationException("Could not find the configuration name and type from the URL '"+url.toString()+"'. ", e);
699                    }
700        }
701        
702        /**
703         * Prints the content of the configuration information file to the system logger
704         * 
705         * @throws MaltChainedException
706         */
707        public void echoInfoFile() throws MaltChainedException {
708            checkConfigDirectory();
709            JarInputStream jis;
710            try {
711                    if (url == null) {
712                            jis = new JarInputStream(new FileInputStream(workingDirectory.getPath()+File.separator+getName()+".mco"));
713                    } else {
714                            jis = new JarInputStream(url.openConnection().getInputStream());
715                    }
716                            JarEntry je;
717    
718                            while ((je = jis.getNextJarEntry()) != null) {
719                            String entryName = je.getName();
720    
721                            if (entryName.endsWith(getName()+"_"+getType()+".info")) {
722                                    int c;
723                                        while ((c = jis.read()) != -1) {
724                                            SystemLogger.logger().info((char)c);
725                                        }   
726                            }
727                            }
728                    jis.close();
729            } catch (FileNotFoundException e) {
730                    throw new ConfigurationException("Could not print configuration information file. The configuration file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be found. ", e);
731            } catch (IOException e) {
732                            throw new ConfigurationException("Could not print configuration information file. ", e);
733                    }
734    
735        }
736        
737        /**
738         * Unpacks the malt configuration file (.mco).
739         * 
740         * @throws MaltChainedException
741         */
742        public void unpackConfigFile() throws MaltChainedException {
743            checkConfigDirectory();
744            JarInputStream jis;
745            try {
746                    if (url == null) {
747                            jis = new JarInputStream(new FileInputStream(workingDirectory.getPath()+File.separator+getName()+".mco"));
748                    } else {
749                            jis = new JarInputStream(url.openConnection().getInputStream());
750                    }
751                    unpackConfigFile(jis);
752                    jis.close();
753            } catch (FileNotFoundException e) {
754                    throw new ConfigurationException("Could not unpack configuration. The configuration file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be found. ", e);
755            } catch (IOException e) {
756                    if (configDirectory.exists()) {
757                            deleteConfigDirectory();
758                    }
759                            throw new ConfigurationException("Could not unpack configuration. ", e);
760                    }
761            initCreatedByMaltParserVersionFromInfoFile();
762        }
763    
764        protected void unpackConfigFile(JarInputStream jis) throws MaltChainedException {
765                    try {
766                            JarEntry je;
767                            byte[] readBuffer = new byte[BUFFER];
768                    SortedSet<String> directoryCache  = new TreeSet<String>();
769                            while ((je = jis.getNextJarEntry()) != null) {
770                            String entryName = je.getName();
771    
772                            if (entryName.startsWith("/")) {
773                                    entryName = entryName.substring(1);
774                            }
775                            if (entryName.endsWith(File.separator) || entryName.endsWith("/")) {
776                                return;
777                            }
778                            int index = -1;
779                            if (File.separator.equals("\\")) {
780                                    entryName = entryName.replace('/', '\\');
781                                    index = entryName.lastIndexOf("\\");
782                            } else if (File.separator.equals("/")) {
783                                    entryName = entryName.replace('\\', '/');
784                                    index = entryName.lastIndexOf("/");
785                            }
786                            if (index > 0) {
787                                String dirName = entryName.substring(0, index);
788                                if (!directoryCache.contains(dirName)) {
789                                    File directory = new File(workingDirectory.getPath()+File.separator+dirName);
790                                    if (!(directory.exists() && directory.isDirectory())) {
791                                        if (!directory.mkdirs()) {
792                                            throw new ConfigurationException("Unable to make directory '" + dirName +"'. ");
793                                        }
794                                        directoryCache.add(dirName);
795                                    }
796                                }
797                            }
798                           
799                            if (new File(workingDirectory.getPath()+File.separator+entryName).isDirectory() && new File(workingDirectory.getPath()+File.separator+entryName).exists()) {
800                                    continue;
801                            }
802                            BufferedOutputStream bos;
803                            try {
804                                    bos = new BufferedOutputStream(new FileOutputStream(workingDirectory.getPath()+File.separator+entryName), BUFFER);
805                            } catch (FileNotFoundException e) {
806                                            throw new ConfigurationException("Could not unpack configuration. The file '"+workingDirectory.getPath()+File.separator+entryName+"' cannot be unpacked. ", e);
807                            }
808                                    int n = 0;
809                                while ((n = jis.read(readBuffer, 0, BUFFER)) != -1) {
810                                    bos.write(readBuffer, 0, n);
811                                }
812                                bos.flush();
813                                bos.close();
814                            }
815                    } catch (IOException e) {
816                            throw new ConfigurationException("Could not unpack configuration. ", e);
817                    }
818        }
819                
820            /**
821             * Returns the name of the configuration directory
822             * 
823             * @return the name of the configuration directory
824             */
825            public String getName() {
826                    return name;
827            }
828    
829            protected void setName(String name) {
830                    this.name = name;
831            }
832    
833            /**
834             * Returns the type of the configuration directory
835             * 
836             * @return the type of the configuration directory
837             */
838            public String getType() {
839                    return type;
840            }
841    
842            protected void setType(String type) {
843                    this.type = type;
844            }
845            
846            /**
847             * Returns a file handler object for the working directory
848             * 
849             * @return a file handler object for the working directory
850             */
851            public File getWorkingDirectory() {
852                    return workingDirectory;
853            }
854    
855            /**
856             * Initialize the working directory
857             * 
858             * @throws MaltChainedException
859             */
860            public void initWorkingDirectory() throws MaltChainedException {
861                    try {
862                            initWorkingDirectory(OptionManager.instance().getOptionValue(0, "config", "workingdir").toString());
863                    } catch (NullPointerException e) {
864                            throw new ConfigurationException("The configuration cannot be found.", e);
865                    }
866            }
867    
868            /**
869             * Initialize the working directory according to the path. If the path is equals to "user.dir" or current directory, then the current directory
870             *  will be the working directory.
871             * 
872             * @param pathPrefixString      the path to the working directory
873             * @throws MaltChainedException
874             */
875            public void initWorkingDirectory(String pathPrefixString) throws MaltChainedException {
876                    if (pathPrefixString == null || pathPrefixString.equalsIgnoreCase("user.dir") || pathPrefixString.equalsIgnoreCase(".")) {
877                            workingDirectory = new File(System.getProperty("user.dir"));
878                    } else {
879                            workingDirectory = new File(pathPrefixString);
880                    }
881    
882                    if (workingDirectory == null || !workingDirectory.isDirectory()) {
883                            new ConfigurationException("The specified working directory '"+pathPrefixString+"' is not a directory. ");
884                    }
885            }
886            
887            /**
888             * Returns the URL to the malt configuration file (.mco) 
889             * 
890             * @return the URL to the malt configuration file (.mco)
891             */
892            public URL getUrl() {
893                    return url;
894            }
895    
896            protected void setUrl(URL url) {
897                    this.url = url;
898            }
899            
900            /**
901             * Returns the option container index
902             * 
903             * @return the option container index
904             */
905            public int getContainerIndex() {
906                    return containerIndex;
907            }
908    
909            /**
910             * Sets the option container index
911             * 
912             * @param containerIndex a option container index
913             */
914            public void setContainerIndex(int containerIndex) {
915                    this.containerIndex = containerIndex;
916            }
917    
918            /**
919             * Returns the version number of MaltParser which created the malt configuration file (.mco)
920             * 
921             * @return the version number of MaltParser which created the malt configuration file (.mco)
922             */
923            public String getCreatedByMaltParserVersion() {
924                    return createdByMaltParserVersion;
925            }
926    
927            /**
928             * Sets the version number of MaltParser which created the malt configuration file (.mco)
929             * 
930             * @param createdByMaltParserVersion a version number of MaltParser
931             */
932            public void setCreatedByMaltParserVersion(String createdByMaltParserVersion) {
933                    this.createdByMaltParserVersion = createdByMaltParserVersion;
934            }
935            
936            public void initCreatedByMaltParserVersionFromInfoFile() throws MaltChainedException {
937                    try {
938                            BufferedReader br = new BufferedReader(getInputStreamReaderFromConfigFileEntry(getName()+"_"+getType()+".info", "UTF-8"));
939                            String line = null;
940                            while ((line = br.readLine()) != null) {
941                                    if (line.startsWith("Version:                       ")) {
942                                            setCreatedByMaltParserVersion(line.substring(31));
943                                            break;
944                                    }
945                            }
946                            br.close();
947                    } catch (FileNotFoundException e) {
948                            throw new ConfigurationException("Could not retrieve the version number of the MaltParser configuration.", e);
949                    } catch (IOException e) {
950                            throw new ConfigurationException("Could not retrieve the version number of the MaltParser configuration.", e);
951                    }
952            }
953            
954            public void versioning() throws MaltChainedException {
955                    initCreatedByMaltParserVersionFromInfoFile();
956                    SystemLogger.logger().info("\nCurrent version      : " + SystemInfo.getVersion() + "\n");
957                    SystemLogger.logger().info("Parser model version : " + createdByMaltParserVersion + "\n");
958                    if (SystemInfo.getVersion() == null) {
959                            throw new ConfigurationException("Couln't determine the version of MaltParser");
960                    } else if (createdByMaltParserVersion == null) {
961                            throw new ConfigurationException("Couln't determine the version of the parser model");
962                    } else if (SystemInfo.getVersion().equals(createdByMaltParserVersion)) {
963                            SystemLogger.logger().info("The parser model "+getName()+".mco has already the same version as the current version of MaltParser. \n");
964                            return;
965                    }
966                    
967                    File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
968                    File newMcoPath = new File(workingDirectory.getPath()+File.separator+getName()+"."+SystemInfo.getVersion().trim()+".mco");
969                    Versioning versioning = new Versioning(name, type, mcoPath, createdByMaltParserVersion);
970                    if (!versioning.support(createdByMaltParserVersion)) {
971                            SystemLogger.logger().warn("The parser model '"+ name+ ".mco' is created by MaltParser "+getCreatedByMaltParserVersion()+", which cannot be converted to a MaltParser "+SystemInfo.getVersion()+" parser model.\n");
972                            SystemLogger.logger().warn("Please retrain the parser model with MaltParser "+SystemInfo.getVersion() +" or download MaltParser "+getCreatedByMaltParserVersion()+" from http://maltparser.org/download.html\n");
973                            return;
974                    }
975                    SystemLogger.logger().info("Converts the parser model '"+ mcoPath.getName()+ "' into '"+newMcoPath.getName()+"'....\n");
976                    copyConfigFile(mcoPath, newMcoPath, versioning);
977            }
978            
979            protected void checkNConvertConfigVersion() throws MaltChainedException {
980                    if (createdByMaltParserVersion.startsWith("1.0")) {
981                            SystemLogger.logger().info("  Converts the MaltParser configuration ");
982                            SystemLogger.logger().info("1.0");
983                            SystemLogger.logger().info(" to ");
984                            SystemLogger.logger().info(SystemInfo.getVersion());
985                            SystemLogger.logger().info("\n");
986                            File[] configFiles = configDirectory.listFiles();
987                            for (int i = 0, n = configFiles.length; i < n; i++) {
988                                    if (configFiles[i].getName().endsWith(".mod")) {
989                                            configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"odm0."+configFiles[i].getName()));
990                                    }
991                                    if (configFiles[i].getName().endsWith(getName()+".dsm")) {
992                                            configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"odm0.dsm"));
993                                    }
994                                    if (configFiles[i].getName().equals("savedoptions.sop")) {
995                                            configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
996                                    }
997                                    if (configFiles[i].getName().equals("symboltables.sym")) {
998                                            configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"symboltables.sym.old"));
999                                    }
1000                            }
1001                            try {
1002                                    BufferedReader br = new BufferedReader(new FileReader(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
1003                                    BufferedWriter bw = new BufferedWriter(new FileWriter(configDirectory.getPath()+File.separator+"savedoptions.sop"));
1004                                    String line;
1005                                    while ((line = br.readLine()) != null) {
1006                                            if (line.startsWith("0\tguide\tprediction_strategy")) {
1007                                                    bw.write("0\tguide\tdecision_settings\tT.TRANS+A.DEPREL\n");
1008                                            } else {
1009                                                    bw.write(line);
1010                                                    bw.write('\n');
1011                                            }
1012                                    }
1013                                    br.close();
1014                                    bw.flush();
1015                                    bw.close();
1016                                    new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old").delete();
1017                            } catch (FileNotFoundException e) {
1018                                    throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
1019                            }  catch (IOException e) {
1020                                    throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
1021                            }               
1022                            try {
1023                                    BufferedReader br = new BufferedReader(new FileReader(configDirectory.getPath()+File.separator+"symboltables.sym.old"));
1024                                    BufferedWriter bw = new BufferedWriter(new FileWriter(configDirectory.getPath()+File.separator+"symboltables.sym"));
1025                                    String line;
1026                                    while ((line = br.readLine()) != null) {
1027                                            if (line.startsWith("AllCombinedClassTable")) {
1028                                                    bw.write("T.TRANS+A.DEPREL\n");
1029                                            } else {
1030                                                    bw.write(line);
1031                                                    bw.write('\n');
1032                                            }
1033                                    }
1034                                    br.close();
1035                                    bw.flush();
1036                                    bw.close();
1037                                    new File(configDirectory.getPath()+File.separator+"symboltables.sym.old").delete();
1038                            } catch (FileNotFoundException e) {
1039                                    throw new ConfigurationException("Could convert symboltables.sym version 1.0.4 to version 1.1. ", e);
1040                            }  catch (IOException e) {
1041                                    throw new ConfigurationException("Could convert symboltables.sym version 1.0.4 to version 1.1. ", e);
1042                            }
1043                    }
1044                    if (!createdByMaltParserVersion.startsWith("1.3")) {
1045                            SystemLogger.logger().info("  Converts the MaltParser configuration ");
1046                            SystemLogger.logger().info(createdByMaltParserVersion);
1047                            SystemLogger.logger().info(" to ");
1048                            SystemLogger.logger().info(SystemInfo.getVersion());
1049                            SystemLogger.logger().info("\n");
1050                            
1051    
1052                            new File(configDirectory.getPath()+File.separator+"savedoptions.sop").renameTo(new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
1053                            try {
1054                                    BufferedReader br = new BufferedReader(new FileReader(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
1055                                    BufferedWriter bw = new BufferedWriter(new FileWriter(configDirectory.getPath()+File.separator+"savedoptions.sop"));
1056                                    String line;
1057                                    while ((line = br.readLine()) != null) {
1058                                            int index = line.indexOf('\t');
1059                                            int container = 0;
1060                                            if (index > -1) {
1061                                                    container = Integer.parseInt(line.substring(0,index));
1062                                            }
1063                                            
1064                                            if (line.startsWith(container+"\tnivre\tpost_processing")) {
1065                                            } else if (line.startsWith(container+"\tmalt0.4\tbehavior")) {
1066                                                    if (line.endsWith("true")) {
1067                                                            SystemLogger.logger().info("MaltParser 1.3 doesn't support MaltParser 0.4 emulation.");
1068                                                            br.close();
1069                                                            bw.flush();
1070                                                            bw.close();
1071                                                            deleteConfigDirectory();
1072                                                            System.exit(0);
1073                                                    }
1074                                            } else if (line.startsWith(container+"\tsinglemalt\tparsing_algorithm")) {
1075                                                    bw.write(container);
1076                                                    bw.write("\tsinglemalt\tparsing_algorithm\t");
1077                                                    if (line.endsWith("NivreStandard")) {
1078                                                            bw.write("class org.maltparser.parser.algorithm.nivre.NivreArcStandardFactory");        
1079                                                    } else if (line.endsWith("NivreEager")) {
1080                                                            bw.write("class org.maltparser.parser.algorithm.nivre.NivreArcEagerFactory");
1081                                                    } else if (line.endsWith("CovingtonNonProjective")) {
1082                                                            bw.write("class org.maltparser.parser.algorithm.covington.CovingtonNonProjFactory");
1083                                                    } else if (line.endsWith("CovingtonProjective")) {
1084                                                            bw.write("class org.maltparser.parser.algorithm.covington.CovingtonProjFactory");
1085                                                    }
1086                                                    bw.write('\n');
1087                                            } else {
1088                                                    bw.write(line);
1089                                                    bw.write('\n');
1090                                            }
1091                                    }
1092                                    br.close();
1093                                    bw.flush();
1094                                    bw.close();
1095                                    new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old").delete();
1096                            } catch (FileNotFoundException e) {
1097                                    throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
1098                            }  catch (IOException e) {
1099                                    throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
1100                            }
1101                    }
1102            }
1103            
1104            /**
1105             * Terminates the configuration directory
1106             * 
1107             * @throws MaltChainedException
1108             */
1109            public void terminate() throws MaltChainedException {
1110                    if (infoFile != null) {
1111                            try {
1112                                    infoFile.flush();
1113                                    infoFile.close();
1114                            } catch (IOException e) {
1115                                    throw new ConfigurationException("Could not close configuration information file. ", e);
1116                            }
1117                    }
1118                    symbolTables = null;
1119    //              configuration = null;
1120            }
1121            
1122            /* (non-Javadoc)
1123             * @see java.lang.Object#finalize()
1124             */
1125            protected void finalize() throws Throwable {
1126                    try {
1127                            if (infoFile != null) {
1128                                    infoFile.flush();
1129                                    infoFile.close();
1130                            }
1131                    } finally {
1132                            super.finalize();
1133                    }
1134            }
1135            
1136            public SymbolTableHandler getSymbolTables() {
1137                    return symbolTables;
1138            }
1139    
1140            public void setSymbolTables(SymbolTableHandler symbolTables) {
1141                    this.symbolTables = symbolTables;
1142            }
1143    
1144            public DataFormatManager getDataFormatManager() {
1145                    return dataFormatManager;
1146            }
1147    
1148            public void setDataFormatManager(DataFormatManager dataFormatManager) {
1149                    this.dataFormatManager = dataFormatManager;
1150            }
1151                    
1152            public Set<String> getDataFormatInstanceKeys() {
1153                    return dataFormatInstances.keySet();
1154            }
1155            
1156            public boolean addDataFormatInstance(String key, DataFormatInstance dataFormatInstance) {
1157                    if (!dataFormatInstances.containsKey(key)) {
1158                            dataFormatInstances.put(key, dataFormatInstance);
1159                            return true;
1160                    }
1161                    return false;
1162            }
1163            
1164            public DataFormatInstance getDataFormatInstance(String key) {
1165                    return dataFormatInstances.get(key);
1166            }
1167            
1168            public int sizeDataFormatInstance() {
1169                    return dataFormatInstances.size();
1170            }
1171            
1172            public DataFormatInstance getInputDataFormatInstance() {
1173                    return dataFormatInstances.get(dataFormatManager.getInputDataFormatSpec().getDataFormatName());
1174            }
1175    
1176            public URL getInputFormatURL() {
1177                    return inputFormatURL;
1178            }
1179    
1180            public URL getOutputFormatURL() {
1181                    return outputFormatURL;
1182            }
1183            
1184            
1185    }