Statistics
| Revision:

root / tmp / org.txm.treetagger.core / src / org / txm / importer / xmltxm / Annotate.groovy @ 1065

History | View | Annotate | Download (18.5 kB)

1
// Copyright © 2010-2013 ENS de Lyon.
2
// Copyright © 2007-2010 ENS de Lyon, CNRS, INRP, University of
3
// Lyon 2, University of Franche-Comté, University of Nice
4
// Sophia Antipolis, University of Paris 3.
5
//
6
// The TXM platform is free software: you can redistribute it
7
// and/or modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation,
9
// either version 2 of the License, or (at your option) any
10
// later version.
11
//
12
// The TXM platform is distributed in the hope that it will be
13
// useful, but WITHOUT ANY WARRANTY; without even the implied
14
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15
// PURPOSE. See the GNU General Public License for more
16
// details.
17
//
18
// You should have received a copy of the GNU General
19
// Public License along with the TXM platform. If not, see
20
// http://www.gnu.org/licenses.
21
//
22
//
23
//
24
// $LastChangedDate: 2016-10-03 15:30:36 +0200 (lun. 03 oct. 2016) $
25
// $LastChangedRevision: 3313 $
26
// $LastChangedBy: mdecorde $
27
//
28
package org.txm.importer.xmltxm
29

    
30
import java.io.File
31
import java.text.DateFormat
32
import java.util.Date
33
import java.util.concurrent.*
34

    
35
import org.txm.Toolbox
36
import org.txm.importer.*
37
import org.txm.scripts.importer.*
38
import org.txm.importer.scripts.xmltxm.AnnotationInjection
39
import org.txm.importer.cwb.*
40
import org.txm.objects.*
41
import org.txm.stat.utils.ConsoleProgressBar;
42
import org.txm.treetagger.core.preferences.TreeTaggerPreferences
43
import org.txm.utils.LangDetector;
44
import org.txm.utils.logger.Log;
45
import org.txm.utils.treetagger.TreeTagger
46

    
47
/**
48
 * Annotate and replace the TEI-TXM files of the folder $rootDirFile/txm with TreeTagger.
49
 * creates $rootDirFile/interp and $rootDirFile/treetagger
50
 *
51
 */
52
class Annotate {
53
        boolean cancelNow = false;
54

    
55
        /** The report file. */
56
        File reportFile;//contains the txm:application tag content
57

    
58
        /** The resp person. */
59
        String respPerson;
60

    
61
        /** The resp id. */
62
        String respId;
63

    
64
        /** The resp desc. */
65
        String respDesc;
66

    
67
        /** The resp date. */
68
        String respDate;
69

    
70
        /** The resp when. */
71
        String respWhen;
72

    
73
        /** The app ident. */
74
        String appIdent;
75

    
76
        /** The app version. */
77
        String appVersion;
78

    
79
        /** The distributor. */
80
        String distributor;
81

    
82
        /** The publi stmt. */
83
        String publiStmt;
84

    
85
        /** The source stmt. */
86
        String sourceStmt;
87

    
88
        /** The types. */
89
        def types;
90

    
91
        /** The types title. */
92
        def typesTITLE;
93

    
94
        /** The types desc. */
95
        def typesDesc;
96

    
97
        /** The types tagset. */
98
        def typesTAGSET;
99

    
100
        /** The types web. */
101
        def typesWEB;
102

    
103
        /** The idform. */
104
        String idform;
105

    
106
        /** The debug. */
107
        boolean debug = false;
108

    
109
        File modelsDirectory;
110

    
111
        public Annotate() {
112
                modelsDirectory = new File(TreeTaggerPreferences.getString(TreeTaggerPreferences.MODELS_PATH, TreeTaggerPreferences.PREFERENCES_NODE)); // default models directory is set in the Toolbox
113
        }
114

    
115
        /**
116
         * Sets the debug.
117
         */
118
        public void setDebug() {
119
                debug = true;
120
        }
121

    
122
        String id;
123
        /**
124
         * Inits the tt outfile infos.
125
         *
126
         * @param rootDirFile the root dir file
127
         * @param modelfile the modelfile
128
         */
129
        public void initTTOutfileInfos(File rootDirFile, File modelfile, String modelfilename)
130
        {
131
                initTTOutfileInfos(rootDirFile, modelfile, modelfilename, null);
132
        }
133

    
134
        /**
135
         * Inits the tt outfile infos.
136
         *
137
         * @param rootDirFile the root dir file
138
         * @param modelfile the modelfile
139
         * @param properties : 2 element array that contains the word properties to create. It can be null (the modelfilename will be used)
140
         */
141
        public void initTTOutfileInfos(File rootDirFile, File modelfile, String modelfilename, String[] properties)
142
        {
143
                id = modelfilename;
144
                String[] split = id.split("\\.");
145
                if (split.length > 0) id = split[0];
146
                if (id.equals("??")) id = "xx"
147

    
148
                reportFile = new File(rootDirFile,"NLPToolsParameters.xml");
149

    
150
                respPerson = System.getProperty("user.name");
151
                respId = "txm";
152
                respDesc = "NLP annotation tool";
153
                respDate = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK).format(new Date());
154
                respWhen = DateFormat.getDateInstance(DateFormat.FULL, Locale.UK).format(new Date());
155

    
156
                appIdent = "TreeTagger";
157
                appVersion = "3.2";
158

    
159
                distributor = "";
160
                publiStmt = """""";
161
                sourceStmt = """""";
162

    
163
                if (properties != null && properties.length == 2) {
164
                        types = [properties[0],properties[1]];
165
                        typesTITLE = [properties[0],properties[1]];
166
                } else {
167
                        types = [id+"pos",id+"lemma"];
168
                        typesTITLE = [id+"pos",id+"lemma"];
169
                }
170

    
171
                //TODO: the tagset, website and description should be referenced in the model catalog
172
                if(modelfile.getName() == "rgaqcj.par") {
173
                        typesDesc = ["CATTEX pos tagset built with BFM texts","fr lemma of the model "+modelfile+" - "]
174
                        typesTAGSET = ["http://bfm.ens-lyon.fr/IMG/pdf/Cattex2009_Manuel.pdf",""]
175
                        typesWEB = ["http://bfm.ens-lyon.fr/",""]
176
                } else {
177
                        typesDesc = ["pos tagset built from model "+modelfile,id+" lemma of the model "+modelfile+" - "]
178
                        typesTAGSET = ["",""]
179
                        typesWEB = ["",""]
180
                }
181

    
182
                idform ="w";
183
        }
184

    
185
        /**
186
         * Apply tt.
187
         *
188
         * @param ttsrcfile the ttsrcfile
189
         * @param ttoutfile the ttoutfile
190
         * @param modelfile the modelfile
191
         * @return true, if successful
192
         */
193
        public boolean applyTT(File ttsrcfile, File ttoutfile, File modelfile) {
194
                applyTT(ttsrcfile, ttoutfile, modelfile, null)
195
        }
196

    
197
        /**
198
         * Apply tt.
199
         *
200
         * @param ttsrcfile the ttsrcfile
201
         * @param ttoutfile the ttoutfile
202
         * @param modelfile the modelfile
203
         * @param options, if null use value set in Toolbox preferences
204
         * @return true, if successful
205
         */
206
        public boolean applyTT(File ttsrcfile, File ttoutfile, File modelfile, String[] options)
207
        {
208
                try {
209
                        File infile = ttsrcfile;
210
                        File outfile = ttoutfile;
211

    
212
                        def tt = new TreeTagger(TreeTaggerPreferences.getString(TreeTaggerPreferences.INSTALL_PATH, TreeTaggerPreferences.PREFERENCES_NODE)+"/bin/", options);
213
                        tt.settoken();
214
                        tt.setlemma();
215
                        tt.setsgml();
216
                        if (TreeTaggerPreferences.getBoolean(TreeTaggerPreferences.OPTIONS_UNKNOWN, TreeTaggerPreferences.PREFERENCES_NODE)) {
217
                                tt.setnounknown();
218
                        }
219
                        tt.seteostag("<s>");
220
                        if (TreeTaggerPreferences.getBoolean(TreeTaggerPreferences.OPTIONS_DEBUG, TreeTaggerPreferences.PREFERENCES_NODE)) {
221
                                tt.debug(true);
222
                        } else {
223
                                tt.setquiet();
224
                        }
225
                        if (TreeTaggerPreferences.getBoolean(TreeTaggerPreferences.OPTIONS_CAPHEURISTIC, TreeTaggerPreferences.PREFERENCES_NODE)) {
226
                                tt.setcapheuristics();
227
                        }
228
                        if (TreeTaggerPreferences.getBoolean(TreeTaggerPreferences.OPTIONS_HYPHENHEURISTIC, TreeTaggerPreferences.PREFERENCES_NODE)) {
229
                                tt.sethyphenheuristics();
230
                        }
231
                        if (TreeTaggerPreferences.getBoolean(TreeTaggerPreferences.OPTIONS_PROB, TreeTaggerPreferences.PREFERENCES_NODE)) {
232
                                tt.setprob();
233
                        }
234
                        
235
                        String lex = TreeTaggerPreferences.getString(TreeTaggerPreferences.OPTIONS_LEX, TreeTaggerPreferences.PREFERENCES_NODE);
236
                        if (lex !=null && lex.length() > 0) {
237
                                tt.setlex(lex);
238
                        }
239
                        String wc = TreeTaggerPreferences.getString(TreeTaggerPreferences.OPTIONS_WC, TreeTaggerPreferences.PREFERENCES_NODE);
240
                        if (wc !=null && wc.length() > 0) {
241
                                tt.setwc(wc);
242
                        }
243
                        tt.treetagger(modelfile.getAbsolutePath(), infile.getAbsolutePath(), outfile.getAbsolutePath())
244
                        infile.delete();
245
                } catch(Exception e) {
246
                        Log.printStackTrace(e);
247
                        System.out.println("Failed to apply TreeTagger on $ttsrcfile input file with the $modelfile model file.");
248
                        return false;
249
                }
250
                return true;
251
        }
252

    
253
        /**
254
         * Write standoff file.
255
         *
256
         * @param ttoutfile the ttoutfile
257
         * @param posfile the posfile
258
         * @return true, if successful
259
         */
260
        public boolean writeStandoffFile(File ttoutfile, File posfile)
261
        {
262
                def encoding ="UTF-8";
263
                def transfo = new CSV2W_ANA();
264
                //println("build w-interp "+ttfile.getName()+ ">>"+posfile.getName())
265
                transfo.setAnnotationTypes( types, typesDesc, typesTAGSET, typesWEB, idform);
266
                transfo.setResp(respId, respDesc, respDate, respPerson, respWhen);
267
                transfo.setApp(appIdent, appVersion);
268
                transfo.setTarget(ttoutfile.getAbsolutePath(), reportFile);
269
                transfo.setInfos(distributor,  publiStmt, sourceStmt);
270
                return transfo.process( ttoutfile, posfile, encoding );
271
        }
272

    
273
        /**
274
         * Run step by step : build TT src files, run TT, build xml-standoff files, inject standoff annotations
275
         *
276
         * @param rootDirFile the root dir file
277
         * @param modelfilename the modelfilename
278
         * @return true, if successful
279
         */
280
        public boolean run(File binDir, File txmDir,  String modelfilename)
281
        {
282
                //test if modelfile exists
283
                if (debug) {
284
                        println "rootDirFile "+binDir
285
                        println "txmDir "+txmDir
286
                        println "TREETAGGER INSTALL PATH : "+TreeTaggerPreferences.getString(TreeTaggerPreferences.INSTALL_PATH, TreeTaggerPreferences.PREFERENCES_NODE);
287
                        println "TREETAGGER MODELS PATH : "+TreeTaggerPreferences.getString(TreeTaggerPreferences.MODELS_PATH, TreeTaggerPreferences.PREFERENCES_NODE)
288
                }
289

    
290
                //test if the Toolbox know TreeTagger
291
                if (!new File(TreeTaggerPreferences.getString(TreeTaggerPreferences.INSTALL_PATH, TreeTaggerPreferences.PREFERENCES_NODE)+"/bin/").exists()) {
292
                        println("Could not find TreeTagger binaries in "+TreeTaggerPreferences.getString(TreeTaggerPreferences.INSTALL_PATH, TreeTaggerPreferences.PREFERENCES_NODE)+"/bin/")
293
                        return false;
294
                }
295
                String langAll = null
296
                String lang;
297
                if (modelfilename.startsWith("??")) {
298
                        langAll = new LangDetector(binDir).getLang();
299
                        println "General lang $langAll"
300
                }
301

    
302
                //cleaning
303
                new File(binDir, "annotations").deleteDir();
304
                new File(binDir, "annotations").mkdir();
305
                new File(binDir, "treetagger").deleteDir();
306
                new File(binDir, "treetagger").mkdir();
307

    
308
                ArrayList<String> milestones = [];
309

    
310
                //BUILD TT FILE READY TO BE TAGGED
311
                List<File> files = txmDir.listFiles()
312

    
313
                println("Building TT source files ("+files.size()+") from directory "+txmDir)
314
                ConsoleProgressBar cpb = new ConsoleProgressBar(files.size())
315
                for (File f : files) {
316
                        cpb.tick()
317
                        File srcfile = f;
318
                        File resultfile = new File(binDir, "treetagger/"+f.getName()+".tt");
319
                        if(debug)
320
                                println "build tt src : "+srcfile+" >> "+resultfile
321
                        def ttsrcbuilder = new BuildTTSrc(srcfile.toURI().toURL())
322
                        if (!ttsrcbuilder.process(resultfile, null))
323
                                System.out.println("Failed to build tt src file of "+srcfile);
324
                }
325

    
326
                if (cancelNow) return;
327

    
328
                File modelDirectory = new File(TreeTaggerPreferences.getString(TreeTaggerPreferences.MODELS_PATH, TreeTaggerPreferences.PREFERENCES_NODE));
329
                if (!modelDirectory.exists()) {
330
                        println "Skipping ANNOTATE: TreeTagger language model file directory not found: "+modelDirectory.getAbsolutePath();
331
                        return false;
332
                } else         if (!modelDirectory.canRead()) {
333
                        println "Skipping ANNOTATE: impossible to access the TreeTagger language model file directory: "+modelDirectory.getAbsolutePath();
334
                        return false;
335
                }
336
                println("")
337
                //Convert encoding if needed
338

    
339
                //APPLY TREETAGGER
340
                files = new File(binDir, "treetagger").listFiles()
341
                println("Applying $modelfilename TreeTagger model on dir: "+new File(binDir, "treetagger")+ " ("+files.size()+" files)")
342
                if (files == null || files.size() == 0)
343
                        return false;
344
                File modelfile;
345
                cpb = new ConsoleProgressBar(files.size())
346
                for (File f : files) {
347
                        String tmpModelFileName = modelfilename
348
                        if (modelfilename.startsWith("??")) {
349
                                lang = langAll;
350
                                if (f.length() > LangDetector.MINIMALSIZE) {
351
                                        lang = new LangDetector(f).getLang();
352
                                        //println "guessing lang $f : $lang"
353
                                }
354
                                tmpModelFileName = lang+".par"
355
                        }
356
                        modelfile = new File(modelsDirectory, tmpModelFileName);
357
                        if (debug)
358
                                println "model file : "+modelfile;
359

    
360
                        File
361

    
362
                        if (!modelfile.exists()) {
363
                                println "Skipping ANNOTATE: '$modelfile' TreeTagger language model file not found."
364
                                if(System.getProperty("os.name").startsWith("Windows") || System.getProperty("os.name").startsWith("Mac"))
365
                                        println "Windows&Mac users: the operating system might be hiding file extensions. Use your file explorer to check the file name."
366
                                return false;
367
                        } else if (!modelfile.canRead()) {
368
                                println "Skipping ANNOTATE: impossible to access the '$modelfile' TreeTagger language model file."
369
                                return false;
370
                        }
371

    
372
                        //                        if (modelfile.getName().equals("sp.par")) {//UTF >> Latin1
373
                        //                                if(debug)
374
                        //                                        println "fix encoding for model "+modelfile
375
                        //                                new EncodingConverter(f, "UTF-8", "ISO-8859-1")
376
                        //                        }
377

    
378
                        cpb.tick()
379
                        File infile = f;
380
                        File outfile = new File(f.getParent(),f.getName()+"-out.tt");
381
                        if (!applyTT(infile, outfile, modelfile)) {
382
                                return false;
383
                        }
384

    
385
                        //                        //Reconvert encoding if needed
386
                        //                        if (modelfile.getName().equals("sp.par")) {
387
                        //                                if(debug)
388
                        //                                        println "convert "+f+" latin1 >> UTF-8"
389
                        //                                new EncodingConverter(f, "ISO-8859-1", "UTF-8")
390
                        //                        }
391
                }
392
                println("")
393

    
394
                if (cancelNow) return;
395

    
396
                //BUILD STAND-OFF FILES
397
                if (modelfile == null) {
398
                        println "no model applied"
399
                        return false;
400
                }
401

    
402
                initTTOutfileInfos(binDir, modelfile, modelfilename);
403
                files = new File(binDir, "treetagger").listFiles()// now contains the result files of TT
404
                println "Building stdoff files ("+files.size()+") from dir:"+new File(binDir, "treetagger")+" to "+new File(binDir, "annotations");
405
                if (files == null || files.size() == 0)
406
                        return false;
407
                cpb = new ConsoleProgressBar(files.size())
408
                for (File ttrezfile : files) {
409
                        cpb.tick()
410
                        File annotfile = new File(binDir, "annotations/"+ttrezfile.getName()+"-STOFF.xml");
411
                        if (!writeStandoffFile(ttrezfile, annotfile))
412
                                println("Failed to build standoff file of "+ttrezfile);
413
                }
414
                println("")
415

    
416
                if (cancelNow) return;
417

    
418
                //INJECT ANNOTATIONS
419
                List<File> interpfiles = new File(binDir, "annotations").listFiles();
420
                List<File> txmfiles = txmDir.listFiles();
421
                if (txmfiles == null) {
422
                        println "No file to annotate in "+txmDir.getAbsolutePath()
423
                        return false;
424
                }
425
                interpfiles.sort(); // same order
426
                txmfiles.sort(); //same order
427
                println "Injecting stdoff files ("+interpfiles.size()+") data from "+new File(binDir, "annotations")+ " to xml-txm files of "+txmDir;
428
                if (interpfiles == null || interpfiles.size() == 0)
429
                        return false;
430
                cpb = new ConsoleProgressBar(interpfiles.size())
431
                for (int i = 0 ; i < interpfiles.size() ; i++) {
432
                        cpb.tick()
433
                        File srcfile = txmfiles.get(i);
434
                        File pos1file = interpfiles.get(i);
435
                        File temp = File.createTempFile("Annotate", "temp", srcfile.getParentFile());
436
                        def builder = new AnnotationInjection(srcfile.toURI().toURL(), pos1file.toURI().toURL());
437
                        if (!builder.process(temp)) {
438
                                return false;
439
                        }
440
                        builder = null;
441

    
442
                        //println "renaming files..."
443
                        if (!(srcfile.delete() && temp.renameTo(srcfile)))
444
                                println "Warning can't rename file "+temp+" to "+srcfile
445
                }
446
                println("")
447
                return true;
448
        }
449

    
450
        public void setModelsDirectory(File modelsDirectory) {
451
                this.modelsDirectory = modelsDirectory;
452
        }
453

    
454
        /**
455
         * Run file by file. Allow to have one different lang per file. Default behavior add new word properties
456
         *
457
         * @param binDir
458
         * @param txmDir
459
         * @param lang associate a file name with a model filename
460
         * @return true, if successful
461
         */
462
        public boolean run(File binDir, File txmDir, HashMap<String, String> langs)
463
        {
464
                return run(binDir, txmDir, langs, false, new String[0], new String[0]);
465
        }
466

    
467
        /**
468
         * Run file by file. Allow to have one different lang per file
469
         *
470
         * @param binDir 
471
         * @param txmDir
472
         * @param lang associate a file name with a model filename
473
         * @param replace, replace or create a word property
474
         * @return true, if successful
475
         */
476
        public boolean run(File binDir, File txmDir, HashMap<String, String> langs, boolean replace, String[] properties, String[] options)
477
        {
478
                if (!new File(TreeTaggerPreferences.getString(TreeTaggerPreferences.INSTALL_PATH, TreeTaggerPreferences.PREFERENCES_NODE)+"/bin/").exists()) {
479
                        println("Path to TreeTagger is wrong "+TreeTaggerPreferences.getString(TreeTaggerPreferences.INSTALL_PATH, TreeTaggerPreferences.PREFERENCES_NODE)+"/bin/")
480
                        return true;
481
                }
482

    
483
                List<File> listfiles = txmDir.listFiles();
484

    
485
                //cleaning
486
                File annotDir = new File(binDir,"annotations");
487
                annotDir.deleteDir();
488
                annotDir.mkdir();
489
                File ptreetaggerDir = new File(binDir,"ptreetagger");
490
                ptreetaggerDir.deleteDir();
491
                ptreetaggerDir.mkdir();
492
                File treetaggerDir = new File(binDir,"treetagger");
493
                treetaggerDir.deleteDir();
494
                treetaggerDir.mkdir();
495

    
496
                int cores = Runtime.getRuntime().availableProcessors()
497
                int coresToUse = Math.max(1.0, cores * 0.7)
498
                ExecutorService pool = Executors.newFixedThreadPool(coresToUse)
499

    
500
                def files = txmDir.listFiles()
501
                ConsoleProgressBar cpb = new ConsoleProgressBar(files.size())
502
                for (File teiFile : files) {
503
                        int counter = 1;
504
                        ThreadFile t = new ThreadFile("TT_"+counter++, teiFile) {
505

    
506
                                                public void run() {
507

    
508
                                                        if (cancelNow) return;
509
                                                        if (langs.get(f.getName()) == null) {
510
                                                                println "Error: no lang defined for file $f"
511
                                                                return;
512
                                                        }
513

    
514
                                                        String lang = langs.get(f.getName());
515
                                                        run(f, lang, binDir, txmDir, replace, properties, options, annotDir, ptreetaggerDir, treetaggerDir)
516

    
517
                                                        cpb.tick();
518
                                                }
519
                                        };
520

    
521
                        pool.execute(t)
522
                }
523

    
524
                pool.shutdown()
525
                pool.awaitTermination(10, TimeUnit.HOURS)
526
                println ""
527
                return true;
528
        }
529
        public boolean run(File f, String lang, File binDir, File txmDir) {
530

    
531
                File annotDir = new File(binDir,"annotations");
532
                annotDir.mkdir();
533
                File ptreetaggerDir = new File(binDir,"ptreetagger");
534
                ptreetaggerDir.mkdir();
535
                File treetaggerDir = new File(binDir,"treetagger");
536
                treetaggerDir.mkdir();
537

    
538
                return run(f, lang, binDir, txmDir, false, new String[0], new String[0], annotDir, ptreetaggerDir, treetaggerDir)
539
        }
540

    
541

    
542
        public boolean run(File f, String lang, File binDir, File txmDir, boolean replace, String[] properties, String[] options, File annotDir, File ptreetaggerDir, File treetaggerDir) {
543

    
544
                File modelfile = new File(modelsDirectory, lang+".par");
545
                if (!modelfile.exists()) {
546
                        println "Error: No Modelfile available for lang "+modelfile+". Continue import process ";
547
                        return false;
548
                }
549
                File annotfile = new File(annotDir, f.getName()+"-STDOFF.xml");
550
                File ttsrcfile = new File(ptreetaggerDir, f.getName()+"-src.tt");
551
                File ttrezfile = new File(treetaggerDir, f.getName()+"-out.tt");
552
                //println ("TT with $model "+f+"+"+annotfile+" > "+ttsrcfile+" > "+ttrezfile);
553

    
554
                //BUILD TT FILE READY TO BE TAGGED
555
                def builder = new BuildTTSrc(f.toURL());
556
                builder.process(ttsrcfile, null);
557

    
558
                //Apply TT
559
                applyTT(ttsrcfile, ttrezfile, modelfile, options);
560

    
561
                //CREATE STANDOFF FILES
562
                initTTOutfileInfos(binDir, modelfile, lang, properties);
563
                writeStandoffFile(ttrezfile, annotfile)
564

    
565
                //INJECT ANNOTATIONS
566
                File tmpFile = new File(txmDir, "temp_"+f.getName())
567
                builder = new AnnotationInjection(f.toURL(), annotfile.toURL(), replace);
568
                builder.process(tmpFile);
569
                if (!(f.delete() && tmpFile.renameTo(f))) println "Warning can't rename file "+tmpFile+" to "+f
570

    
571
                return f.exists();
572
        }
573

    
574
        public void setCancelNow() {
575
                cancelNow = true;
576
        }
577

    
578
        public class ThreadFile extends Thread {
579
                File f;
580
                public ThreadFile(String name, File f) {
581
                        this.setName(name)
582
                        this.f = f;
583
                }
584
        }
585
}