1   /*
2    *  Copyright (c) 1998-2005, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  Valentin Tablan 23/01/2001
10   *
11   *  $Id: NameBearerHandle.java,v 1.84 2005/12/21 16:14:04 valyt Exp $
12   *
13   */
14  
15  package gate.gui;
16  
17  import java.awt.*;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.KeyEvent;
20  import java.io.*;
21  import java.net.MalformedURLException;
22  import java.net.URL;
23  import java.text.NumberFormat;
24  import java.util.*;
25  import java.util.List;
26  
27  import javax.swing.*;
28  import javax.swing.filechooser.FileFilter;
29  
30  import gate.*;
31  import gate.creole.*;
32  import gate.creole.ir.*;
33  import gate.event.*;
34  import gate.persist.PersistenceException;
35  import gate.security.*;
36  import gate.security.SecurityException;
37  import gate.swing.XJMenuItem;
38  import gate.swing.XJPopupMenu;
39  import gate.util.*;
40  
41  /**
42   * Class used to store the GUI information about an open entity (resource,
43   * controller, datastore).
44   * Such information will include icon to be used for tree components,
45   * popup menu for right click events, large and small views, etc.
46   */
47  public class NameBearerHandle implements Handle,
48                                           StatusListener,
49                                           ProgressListener, CreoleListener {
50  
51    public NameBearerHandle(NameBearer target, Window window) {
52      this.target = target;
53      this.window = window;
54      actionPublishers = new ArrayList();
55  
56      sListenerProxy = new ProxyStatusListener();
57      String iconName = null;
58      if(target instanceof Resource){
59        rData = (ResourceData)Gate.getCreoleRegister().
60                                                get(target.getClass().getName());
61        if(rData != null){
62          iconName = rData.getIcon();
63          if(iconName == null){
64            if(target instanceof LanguageResource) iconName = "lr.gif";
65            else if(target instanceof ProcessingResource) iconName = "pr.gif";
66            else if(target instanceof Controller) iconName = "controller.gif";
67          }
68          tooltipText = "<HTML> <b>" + rData.getComment() + "</b><br>(<i>" +
69                        rData.getClassName() + "</i>)</HTML>";
70        } else {
71          this.icon = MainFrame.getIcon("lr.gif");
72        }
73      }else if(target instanceof DataStore){
74        iconName = ((DataStore)target).getIconName();
75        tooltipText = ((DataStore)target).getComment();
76      }
77  
78      title = (String)target.getName();
79      this.icon = MainFrame.getIcon(iconName);
80  
81      Gate.getCreoleRegister().addCreoleListener(this);
82  
83      if(target instanceof ActionsPublisher) actionPublishers.add(target);
84  
85      buildStaticPopupItems();
86      
87      viewsBuilt = false;
88    }//public DefaultResourceHandle(FeatureBearer res)
89  
90    public Icon getIcon(){
91      return icon;
92    }
93  
94    public void setIcon(Icon icon){
95      this.icon = icon;
96    }
97  
98    public String getTitle(){
99      return title;
100   }
101 
102   public void setTitle(String newTitle){
103     this.title = newTitle;
104   }
105 
106   /**
107    * Returns <tt>true</tt> if the views have already been built for this handle.
108    * @return a <tt>boolean</tt> value.
109    */
110   public boolean viewsBuilt(){
111     return viewsBuilt;
112   }
113   
114   
115   /**
116    * Returns a GUI component to be used as a small viewer/editor, e.g. below
117    * the main tree in the Gate GUI for the selected resource
118    */
119   public JComponent getSmallView() {
120     if(!viewsBuilt)buildViews();
121     return smallView;
122   }
123 
124   /**
125    * Returns the large view for this resource. This view will go into the main
126    * display area.
127    */
128   public JComponent getLargeView() {
129     if(!viewsBuilt) buildViews();
130     return largeView;
131   }
132 
133   public JPopupMenu getPopup() {
134     JPopupMenu popup = new XJPopupMenu();
135     //first add the static items
136     Iterator itemIter = staticPopupItems.iterator();
137     while(itemIter.hasNext()){
138       JMenuItem anItem = (JMenuItem)itemIter.next();
139       if(anItem == null) popup.addSeparator();
140       else popup.add(anItem);
141     }
142 
143     //next add the dynamic list from the target and its editors
144     Iterator publishersIter = actionPublishers.iterator();
145     while(publishersIter.hasNext()){
146       ActionsPublisher aPublisher = (ActionsPublisher)publishersIter.next();
147       if(aPublisher.getActions() != null){
148         Iterator actionIter = aPublisher.getActions().iterator();
149         while(actionIter.hasNext()){
150           Action anAction = (Action)actionIter.next();
151           if(anAction == null) popup.addSeparator();
152           else{
153             popup.add(new XJMenuItem(anAction, sListenerProxy));
154           }
155         }
156       }
157     }
158 
159     return popup;
160   }
161 
162   public String getTooltipText() {
163     return tooltipText;
164   }
165 
166   public void setTooltipText(String text) {
167     this.tooltipText = text;
168   }
169 
170   public Object getTarget() {
171     return target;
172   }
173 
174   public Action getCloseAction(){
175     return new CloseAction();
176   }
177 
178   /** Fill Protege save, save as and save in format actions */
179   private void fillProtegeActions(List popupItems) {
180     Action action;
181 
182     popupItems.add(null);
183 
184     action = new edu.stanford.smi.protege.action.SaveProject();
185     action.putValue(Action.NAME, "Save Protege");
186     action.putValue(Action.SHORT_DESCRIPTION, "Save protege project");
187     // Add Save Protege action
188     popupItems.add(new XJMenuItem(action, this));
189 
190     action = new edu.stanford.smi.protege.action.SaveAsProject();
191     action.putValue(Action.NAME, "Save Protege As...");
192     action.putValue(Action.SHORT_DESCRIPTION, "Save protege project as");
193     // Add Save as... Protege action
194     popupItems.add(new XJMenuItem(action, this));
195 
196     action = new edu.stanford.smi.protege.action.ChangeProjectStorageFormat();
197     // Add Save in format... Protege action
198     popupItems.add(new XJMenuItem(action, this));
199 
200     popupItems.add(null);
201     action = new edu.stanford.smi.protege.action.BuildProject();
202     // Add Import... Protege action
203     popupItems.add(new XJMenuItem(action, this));
204   } // fillProtegeActions(gate.gui.ProtegeWrapper protege)
205 
206   /** Fill HMM Save and Save As... actions */
207   private void fillHMMActions(List popupItems) {
208     Action action;
209 
210     com.ontotext.gate.hmm.agent.AlternativeHMMAgent hmmPR =
211       (com.ontotext.gate.hmm.agent.AlternativeHMMAgent) target;
212 
213     popupItems.add(null);
214     action = new com.ontotext.gate.hmm.agent.SaveAction(hmmPR);
215     action.putValue(Action.SHORT_DESCRIPTION,
216       "Save trained HMM model into PR URL file");
217     // Add Save trained HMM model action
218     popupItems.add(new XJMenuItem(action, sListenerProxy));
219 
220     action = new com.ontotext.gate.hmm.agent.SaveAsAction(hmmPR);
221     action.putValue(Action.SHORT_DESCRIPTION,
222       "Save trained HMM model into new file");
223     // Add Save As... trained HMM model action
224     popupItems.add(new XJMenuItem(action, sListenerProxy));
225   } // fillHMMActions(gate.gui.ProtegeWrapper protege)
226 
227 
228 //  protected JPopupMenu buildPopup(){
229 //    //build the popup
230 //    JPopupMenu popup = new JPopupMenu();
231 //    XJMenuItem closeItem = new XJMenuItem(new CloseAction(), sListenerProxy);
232 //    closeItem.setAccelerator(KeyStroke.getKeyStroke(
233 //                                KeyEvent.VK_F4, ActionEvent.CTRL_MASK));
234 //    popup.add(closeItem);
235 //
236 //    if(target instanceof ProcessingResource){
237 //      popup.addSeparator();
238 //      popup.add(new XJMenuItem(new ReloadAction(), sListenerProxy));
239 //      if(target instanceof gate.ml.DataCollector){
240 //        popup.add(new DumpArffAction());
241 //      }
242 //      if(target instanceof com.ontotext.gate.hmm.agent.AlternativeHMMAgent) {
243 //        fillHMMActions(popup);
244 //      } // if
245 //    }else if(target instanceof LanguageResource) {
246 //      //Language Resources
247 //      popup.addSeparator();
248 //      popup.add(new XJMenuItem(new SaveAction(), sListenerProxy));
249 //      popup.add(new XJMenuItem(new SaveToAction(), sListenerProxy));
250 //      if(target instanceof gate.TextualDocument){
251 //        XJMenuItem saveAsXmlItem =
252 //                         new XJMenuItem(new SaveAsXmlAction(), sListenerProxy);
253 //        saveAsXmlItem.setAccelerator(KeyStroke.getKeyStroke(
254 //                                        KeyEvent.VK_X, ActionEvent.CTRL_MASK));
255 //
256 //        popup.add(saveAsXmlItem);
257 //        XJMenuItem savePreserveFormatItem =
258 //                         new XJMenuItem(new DumpPreserveFormatAction(),
259 //                                        sListenerProxy);
260 //        popup.add(savePreserveFormatItem);
261 //      }else if(target instanceof Corpus){
262 //        popup.addSeparator();
263 //        corpusFiller = new CorpusFillerComponent();
264 //        popup.add(new XJMenuItem(new PopulateCorpusAction(), sListenerProxy));
265 //        popup.addSeparator();
266 //        popup.add(new XJMenuItem(new SaveCorpusAsXmlAction(false), sListenerProxy));
267 //        popup.add(new XJMenuItem(new SaveCorpusAsXmlAction(true), sListenerProxy));
268 //        if (target instanceof IndexedCorpus){
269 //          popup.addSeparator();
270 //          popup.add(new XJMenuItem(new CreateIndexAction(), sListenerProxy));
271 //          popup.add(new XJMenuItem(new OptimizeIndexAction(), sListenerProxy));
272 //          popup.add(new XJMenuItem(new DeleteIndexAction(), sListenerProxy));
273 //        }
274 //      }
275 //      if (target instanceof gate.creole.ProtegeProjectName){
276 //        fillProtegeActions(popup);
277 //      }// End if
278 //    }else if(target instanceof Controller){
279 //      //Applications
280 //      popup.addSeparator();
281 //      popup.add(new XJMenuItem(new DumpToFileAction(), sListenerProxy));
282 //    }
283 //
284 //    //add the custom actions from the resource if any are provided
285 //    if(target instanceof ActionsPublisher){
286 //      Iterator actionsIter = ((ActionsPublisher)target).getActions().iterator();
287 //      while(actionsIter.hasNext()){
288 //        Action anAction = (Action)actionsIter.next();
289 //        if(anAction == null) popup.addSeparator();
290 //        else{
291 //          if(window instanceof StatusListener)
292 //            popup.add(new XJMenuItem(anAction, (StatusListener)window));
293 //          else popup.add(anAction);
294 //        }
295 //      }
296 //    }
297 //    return popup;
298 //  }
299 
300   protected void buildStaticPopupItems(){
301     //build the static part of the popup
302     staticPopupItems = new ArrayList();
303 
304     XJMenuItem closeItem = new XJMenuItem(new CloseAction(), sListenerProxy);
305     closeItem.setAccelerator(KeyStroke.getKeyStroke(
306                                 KeyEvent.VK_F4, ActionEvent.CTRL_MASK));
307     staticPopupItems.add(closeItem);
308 
309     if(target instanceof ProcessingResource){
310       staticPopupItems.add(null);
311       staticPopupItems.add(new XJMenuItem(new ReloadAction(), sListenerProxy));
312       if(target instanceof com.ontotext.gate.hmm.agent.AlternativeHMMAgent) {
313         fillHMMActions(staticPopupItems);
314       } // if
315     }else if(target instanceof LanguageResource) {
316       //Language Resources
317       staticPopupItems.add(null);
318       staticPopupItems.add(new XJMenuItem(new SaveAction(), sListenerProxy));
319       staticPopupItems.add(new XJMenuItem(new SaveToAction(), sListenerProxy));
320       if(target instanceof gate.TextualDocument){
321         XJMenuItem saveAsXmlItem =
322                          new XJMenuItem(new SaveAsXmlAction(), sListenerProxy);
323         saveAsXmlItem.setAccelerator(KeyStroke.getKeyStroke(
324                                         KeyEvent.VK_X, ActionEvent.CTRL_MASK));
325 
326         staticPopupItems.add(saveAsXmlItem);
327       }else if(target instanceof Corpus){
328         staticPopupItems.add(null);
329         corpusFiller = new CorpusFillerComponent();
330         staticPopupItems.add(new XJMenuItem(new PopulateCorpusAction(), sListenerProxy));
331         staticPopupItems.add(null);
332         staticPopupItems.add(new XJMenuItem(new SaveCorpusAsXmlAction(false), sListenerProxy));
333 //        staticPopupItems.add(new XJMenuItem(new SaveCorpusAsXmlAction(true), sListenerProxy));
334         if (target instanceof IndexedCorpus){
335           staticPopupItems.add(null);
336           staticPopupItems.add(new XJMenuItem(new CreateIndexAction(), sListenerProxy));
337           staticPopupItems.add(new XJMenuItem(new OptimizeIndexAction(), sListenerProxy));
338           staticPopupItems.add(new XJMenuItem(new DeleteIndexAction(), sListenerProxy));
339         }
340       }
341       if (target instanceof gate.creole.ProtegeProjectName){
342         fillProtegeActions(staticPopupItems);
343       }// End if
344     }else if(target instanceof Controller){
345       //Applications
346       staticPopupItems.add(null);
347       staticPopupItems.add(new XJMenuItem(new DumpToFileAction(), sListenerProxy));
348     }    
349   }
350 
351   protected void buildViews() {
352     viewsBuilt = true;
353     fireStatusChanged("Building views...");
354 
355     //build the large views
356     List largeViewNames = Gate.getCreoleRegister().
357                           getLargeVRsForResource(target.getClass().getName());
358     if(largeViewNames != null && !largeViewNames.isEmpty()){
359       largeView = new JTabbedPane(JTabbedPane.BOTTOM);
360       Iterator classNameIter = largeViewNames.iterator();
361       while(classNameIter.hasNext()){
362         try{
363           String className = (String)classNameIter.next();
364           ResourceData rData = (ResourceData)Gate.getCreoleRegister().
365                                                   get(className);
366           FeatureMap params = Factory.newFeatureMap();
367           FeatureMap features = Factory.newFeatureMap();
368           Gate.setHiddenAttribute(features, true);
369           VisualResource view = (VisualResource)
370                                 Factory.createResource(className,
371                                                        params,
372                                                        features);
373           view.setTarget(target);
374           view.setHandle(this);
375           ((JTabbedPane)largeView).add((Component)view, rData.getName());
376           //if view provide actions, add it to the list of action puiblishers
377           if(view instanceof ActionsPublisher) actionPublishers.add(view);
378         }catch(ResourceInstantiationException rie){
379           rie.printStackTrace(Err.getPrintWriter());
380         }
381       }
382       if(largeViewNames.size() == 1){
383         largeView = (JComponent)((JTabbedPane)largeView).getComponentAt(0);
384       }else{
385         ((JTabbedPane)largeView).setSelectedIndex(0);
386       }
387     }
388 
389     //build the small views
390     List smallViewNames = Gate.getCreoleRegister().
391                           getSmallVRsForResource(target.getClass().getName());
392     if(smallViewNames != null && !smallViewNames.isEmpty()){
393       smallView = new JTabbedPane(JTabbedPane.BOTTOM);
394       Iterator classNameIter = smallViewNames.iterator();
395       while(classNameIter.hasNext()){
396         try{
397           String className = (String)classNameIter.next();
398           ResourceData rData = (ResourceData)Gate.getCreoleRegister().
399                                                   get(className);
400           FeatureMap params = Factory.newFeatureMap();
401           FeatureMap features = Factory.newFeatureMap();
402           Gate.setHiddenAttribute(features, true);
403           VisualResource view = (VisualResource)
404                                 Factory.createResource(className,
405                                                        params,
406                                                        features);
407           view.setTarget(target);
408           view.setHandle(this);
409           ((JTabbedPane)smallView).add((Component)view, rData.getName());
410           if(view instanceof ActionsPublisher) actionPublishers.add(view);
411         }catch(ResourceInstantiationException rie){
412           rie.printStackTrace(Err.getPrintWriter());
413         }
414       }
415       if(smallViewNames.size() == 1){
416         smallView = (JComponent)((JTabbedPane)smallView).getComponentAt(0);
417       }else{
418         ((JTabbedPane)smallView).setSelectedIndex(0);
419       }
420     }
421     fireStatusChanged("Views built!");
422 
423     
424     // Add the CTRL +F4 key & action combination to the resource
425     JComponent largeView = this.getLargeView();
426     if (largeView != null){
427       largeView.getActionMap().put("Close resource",
428                         new CloseAction());
429       if (target instanceof gate.TextualDocument){
430         largeView.getActionMap().put("Save As XML", new SaveAsXmlAction());
431       }// End if
432     }// End if
433   }//protected void buildViews
434 
435   public String toString(){ return title;}
436 
437   public synchronized void removeProgressListener(ProgressListener l) {
438     if (progressListeners != null && progressListeners.contains(l)) {
439       Vector v = (Vector) progressListeners.clone();
440       v.removeElement(l);
441       progressListeners = v;
442     }
443   }//public synchronized void removeProgressListener(ProgressListener l)
444 
445   public synchronized void addProgressListener(ProgressListener l) {
446     Vector v = progressListeners == null ? new Vector(2) : (Vector) progressListeners.clone();
447     if (!v.contains(l)) {
448       v.addElement(l);
449       progressListeners = v;
450     }
451   }//public synchronized void addProgressListener(ProgressListener l)
452 
453   String title;
454   String tooltipText;
455   NameBearer target;
456 
457   /**
458    * Stores all the action providers for this resource.
459    * They will be questioned when the getPopup() method is called.
460    */
461   protected List actionPublishers;
462 
463   /**
464    * A list of menu items that constitute the static part of the popup.
465    * Null values are used for separators.
466    */
467   protected List staticPopupItems;
468 
469   /**
470    * The top level GUI component this hadle belongs to.
471    */
472   Window window;
473   ResourceData rData;
474   Icon icon;
475   JComponent smallView;
476   JComponent largeView;
477   
478   protected boolean viewsBuilt = false;
479 
480   /**
481    * Component used to select the options for corpus populating
482    */
483   CorpusFillerComponent corpusFiller;
484 
485   StatusListener sListenerProxy;
486 
487 //  File currentDir = null;
488   private transient Vector progressListeners;
489   private transient Vector statusListeners;
490 
491   class CloseAction extends AbstractAction {
492     public CloseAction() {
493       super("Close");
494       putValue(SHORT_DESCRIPTION, "Removes this resource from the system");
495     }
496 
497     public void actionPerformed(ActionEvent e){
498       if(target instanceof Resource){
499         Factory.deleteResource((Resource)target);
500       }else if(target instanceof DataStore){
501         try{
502           ((DataStore)target).close();
503         } catch(PersistenceException pe){
504           JOptionPane.showMessageDialog(largeView != null ?
505                                                      largeView : smallView,
506                                         "Error!\n" + pe.toString(),
507                                         "GATE", JOptionPane.ERROR_MESSAGE);
508         }
509       }
510 
511       statusListeners.clear();
512       progressListeners.clear();
513 //      //delete the viewers
514 //      if(largeView instanceof VisualResource){
515 //        Factory.deleteResource((VisualResource)largeView);
516 //      }else if(largeView instanceof JTabbedPane){
517 //        Component[] comps = ((JTabbedPane)largeView).getComponents();
518 //        for(int i = 0; i < comps.length; i++){
519 //          if(comps[i] instanceof VisualResource)
520 //            Factory.deleteResource((VisualResource)comps[i]);
521 //        }
522 //      }
523 //      if(smallView instanceof VisualResource){
524 //        Factory.deleteResource((VisualResource)smallView);
525 //      }else if(smallView instanceof JTabbedPane){
526 //        Component[] comps = ((JTabbedPane)smallView).getComponents();
527 //        for(int i = 0; i < comps.length; i++){
528 //          if(comps[i] instanceof VisualResource)
529 //            Factory.deleteResource((VisualResource)comps[i]);
530 //        }
531 //      }
532 //
533     }//public void actionPerformed(ActionEvent e)
534   }//class CloseAction
535 
536   /**
537    * Used to save a document as XML
538    */
539   class SaveAsXmlAction extends AbstractAction {
540     public SaveAsXmlAction(){
541       super("Save As Xml...");
542       putValue(SHORT_DESCRIPTION, "Saves this resource in XML");
543     }// SaveAsXmlAction()
544 
545     public void actionPerformed(ActionEvent e) {
546       Runnable runableAction = new Runnable(){
547         public void run(){
548           JFileChooser fileChooser = MainFrame.getFileChooser();
549           File selectedFile = null;
550 
551           List filters = Arrays.asList(fileChooser.getChoosableFileFilters());
552           Iterator filtersIter = filters.iterator();
553           FileFilter filter = null;
554           if(filtersIter.hasNext()){
555             filter = (FileFilter)filtersIter.next();
556             while(filtersIter.hasNext() &&
557                   filter.getDescription().indexOf("XML") == -1){
558               filter = (FileFilter)filtersIter.next();
559             }
560           }
561           if(filter == null || filter.getDescription().indexOf("XML") == -1){
562             //no suitable filter found, create a new one
563             ExtensionFileFilter xmlFilter = new ExtensionFileFilter();
564             xmlFilter.setDescription("XML files");
565             xmlFilter.addExtension("xml");
566             xmlFilter.addExtension("gml");
567             fileChooser.addChoosableFileFilter(xmlFilter);
568             filter = xmlFilter;
569           }
570           fileChooser.setFileFilter(filter);
571 
572           fileChooser.setMultiSelectionEnabled(false);
573           fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
574           fileChooser.setDialogTitle("Select document to save ...");
575           fileChooser.setSelectedFiles(null);
576 
577           int res = (getLargeView() != null) ?
578                                   fileChooser.showDialog(getLargeView(), "Save"):
579                     (getSmallView() != null) ?
580                                   fileChooser.showDialog(getSmallView(), "Save") :
581                                               fileChooser.showDialog(null, "Save");
582           if(res == JFileChooser.APPROVE_OPTION){
583             selectedFile = fileChooser.getSelectedFile();
584             File currentDir = fileChooser.getCurrentDirectory();
585             if(selectedFile == null) return;
586             long start = System.currentTimeMillis();
587             NameBearerHandle.this.statusChanged("Saving as XML to " +
588              selectedFile.toString() + "...");
589             try{
590               MainFrame.lockGUI("Saving...");
591               // Prepare to write into the xmlFile using the original encoding
592               ////////////////////////////////
593               String encoding = ((gate.TextualDocument)target).getEncoding();
594 
595               OutputStreamWriter writer = new OutputStreamWriter(
596                                             new FileOutputStream(selectedFile),
597                                             encoding);
598 
599               // Write (test the toXml() method)
600               // This Action is added only when a gate.Document is created.
601               // So, is for sure that the resource is a gate.Document
602               writer.write(((gate.Document)target).toXml());
603               writer.flush();
604               writer.close();
605             } catch (Exception ex){
606               ex.printStackTrace(Out.getPrintWriter());
607             }finally{
608               MainFrame.unlockGUI();
609             }
610             long time = System.currentTimeMillis() - start;
611             NameBearerHandle.this.statusChanged("Finished saving as xml into "+
612              " the file: " + selectedFile.toString() +
613              " in " + ((double)time) / 1000 + " s");
614           }// End if
615         }// End run()
616       };// End Runnable
617       Thread thread = new Thread(runableAction, "");
618       thread.setPriority(Thread.MIN_PRIORITY);
619       thread.start();
620     }// actionPerformed()
621   }// SaveAsXmlAction
622 
623 
624   /**
625    * Saves a corpus as a set of xml files in a directory.
626    */
627   class SaveCorpusAsXmlAction extends AbstractAction {
628     private boolean preserveFormat;
629     public SaveCorpusAsXmlAction(boolean preserveFormat){
630       super("Save As Xml...");
631       putValue(SHORT_DESCRIPTION, "Saves this corpus in XML");
632       this.preserveFormat = preserveFormat;
633 
634       if(preserveFormat) {
635         putValue(NAME, "Save As Xml preserve format...");
636         putValue(SHORT_DESCRIPTION, "Saves this corpus in XML preserve format");
637       } // if
638     }// SaveAsXmlAction()
639 
640     public void actionPerformed(ActionEvent e) {
641       Runnable runnable = new Runnable(){
642         public void run(){
643 if(preserveFormat) System.out.println("Preserve option set!");
644           try{
645             //we need a directory
646             JFileChooser filer = MainFrame.getFileChooser();
647             filer.setDialogTitle(
648                 "Select the directory that will contain the corpus");
649             filer.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
650             filer.setFileFilter(filer.getAcceptAllFileFilter());
651 
652             if (filer.showDialog(getLargeView() != null ?
653                                      getLargeView() :
654                                      getSmallView(),
655                                      "Select") == JFileChooser.APPROVE_OPTION){
656 
657               File dir = filer.getSelectedFile();
658               //create the top directory if needed
659               if(!dir.exists()){
660                 if(!dir.mkdirs()){
661                   JOptionPane.showMessageDialog(
662                     largeView != null ?largeView : smallView,
663                     "Could not create top directory!",
664                     "GATE", JOptionPane.ERROR_MESSAGE);
665                   return;
666                 }
667               }
668 
669               MainFrame.lockGUI("Saving...");
670 
671               //iterate through all the docs and save each of them as xml
672               Corpus corpus = (Corpus)target;
673               Iterator docIter = corpus.iterator();
674               boolean overwriteAll = false;
675               int docCnt = corpus.size();
676               int currentDocIndex = 0;
677               while(docIter.hasNext()){
678                 boolean docWasLoaded = corpus.isDocumentLoaded(currentDocIndex);
679                 Document currentDoc = (Document)docIter.next();
680                 URL sourceURL = currentDoc.getSourceUrl();
681                 String fileName = null;
682                 if(sourceURL != null){
683                   fileName = sourceURL.getFile();
684                   fileName = Files.getLastPathComponent(fileName);
685                 }
686                 if(fileName == null || fileName.length() == 0){
687                   fileName = currentDoc.getName();
688                 }
689                 if(!fileName.toLowerCase().endsWith(".xml")) fileName += ".xml";
690                 File docFile = null;
691                 boolean nameOK = false;
692                 do{
693                   docFile = new File(dir, fileName);
694                   if(docFile.exists() && !overwriteAll){
695                     //ask the user if we can ovewrite the file
696                     Object[] options = new Object[] {"Yes", "All",
697                                                      "No", "Cancel"};
698                     MainFrame.unlockGUI();
699                     int answer = JOptionPane.showOptionDialog(
700                       largeView != null ? largeView : smallView,
701                       "File " + docFile.getName() + " already exists!\n" +
702                       "Overwrite?" ,
703                       "GATE", JOptionPane.DEFAULT_OPTION,
704                       JOptionPane.WARNING_MESSAGE, null, options, options[2]);
705                     MainFrame.lockGUI("Saving...");
706                     switch(answer){
707                       case 0: {
708                         nameOK = true;
709                         break;
710                       }
711                       case 1: {
712                         nameOK = true;
713                         overwriteAll = true;
714                         break;
715                       }
716                       case 2: {
717                         //user said NO, allow them to provide an alternative name;
718                         MainFrame.unlockGUI();
719                         fileName = (String)JOptionPane.showInputDialog(
720                             largeView != null ? largeView : smallView,
721                             "Please provide an alternative file name",
722                             "GATE", JOptionPane.QUESTION_MESSAGE,
723                             null, null, fileName);
724                         if(fileName == null){
725                           fireProcessFinished();
726                           return;
727                         }
728                         MainFrame.lockGUI("Saving");
729                         break;
730                       }
731                       case 3: {
732                         //user gave up; return
733                         fireProcessFinished();
734                         return;
735                       }
736                     }
737 
738                   }else{
739                     nameOK = true;
740                   }
741                 }while(!nameOK);
742                 //save the file
743                 try{
744                   String content = "";
745                   // check for preserve format flag
746                   if(preserveFormat) {
747                     Set annotationsToDump = null;
748                     // Find the shown document editor.
749                     // If none, just dump the original markup annotations,
750                     // i.e., leave the annotationsToDump null
751                     if (largeView instanceof JTabbedPane) {
752                       Component shownComponent =
753                         ((JTabbedPane) largeView).getSelectedComponent();
754                       if (shownComponent instanceof DocumentEditor) {
755                         // so we only get annotations for dumping
756                         // if they are shown in the table of the document editor,
757                         // which is currently in front of the user
758                         annotationsToDump =
759                           ((DocumentEditor) shownComponent).getDisplayedAnnotations();
760                       }//if we have a document editor
761                     }//if tabbed pane
762 
763                     //determine if the features need to be saved first
764                     Boolean featuresSaved =
765                         Gate.getUserConfig().getBoolean(
766                           GateConstants.SAVE_FEATURES_WHEN_PRESERVING_FORMAT);
767                     boolean saveFeatures = true;
768                     if (featuresSaved != null)
769                       saveFeatures = featuresSaved.booleanValue();
770 
771                     // Write with the toXml() method
772                     content = currentDoc.toXml(annotationsToDump, saveFeatures);
773                   }
774                   else {
775                     content = currentDoc.toXml();
776                   } // if
777 
778                   // Prepare to write into the xmlFile using the original encoding
779                   String encoding = ((gate.TextualDocument)currentDoc).getEncoding();
780 
781                   OutputStreamWriter writer = new OutputStreamWriter(
782                                                 new FileOutputStream(docFile),
783                                                 encoding);
784 
785                   writer.write(content);
786                   writer.flush();
787                   writer.close();
788                 }catch(IOException ioe){
789                   MainFrame.unlockGUI();
790                   JOptionPane.showMessageDialog(
791                     largeView != null ? largeView : smallView,
792                     "Could not create write file:" +
793                     ioe.toString(),
794                     "GATE", JOptionPane.ERROR_MESSAGE);
795                   ioe.printStackTrace(Err.getPrintWriter());
796                   return;
797                 }
798 
799                 fireStatusChanged(currentDoc.getName() + " saved");
800                 //close the doc if it wasn't already loaded
801                 if(!docWasLoaded){
802                   corpus.unloadDocument(currentDoc);
803                   Factory.deleteResource(currentDoc);
804                 }
805 
806                 fireProgressChanged(100 * currentDocIndex++ / docCnt);
807               }//while(docIter.hasNext())
808               fireStatusChanged("Corpus saved");
809               fireProcessFinished();
810             }//select directory
811           }finally{
812             MainFrame.unlockGUI();
813           }
814         }//public void run(){
815       };//Runnable runnable = new Runnable()
816       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
817                                  runnable, "Corpus XML dumper");
818       thread.setPriority(Thread.MIN_PRIORITY);
819       thread.start();
820 
821     }//public void actionPerformed(ActionEvent e)
822   }//class SaveCorpusAsXmlAction extends AbstractAction
823 
824   /**
825    * Saves a corpus as a set of xml files in a directory.
826    */
827   class ReloadClassAction extends AbstractAction {
828     public ReloadClassAction(){
829       super("Reload resource class");
830       putValue(SHORT_DESCRIPTION, "Reloads the java class for this resource");
831     }// SaveAsXmlAction()
832 
833     public void actionPerformed(ActionEvent e) {
834       int answer = JOptionPane.showOptionDialog(
835                 largeView != null ? largeView : smallView,
836                 "This is an advanced option!\n" +
837                 "You should not use this unless your name is Hamish.\n" +
838                 "Are you sure you want to do this?" ,
839                 "GATE", JOptionPane.YES_NO_OPTION,
840                 JOptionPane.WARNING_MESSAGE, null, null, null);
841       if(answer == JOptionPane.OK_OPTION){
842         try{
843           String className = target.getClass().getName();
844           Gate.getClassLoader().reloadClass(className);
845           fireStatusChanged("Class " + className + " reloaded!");
846         }catch(Exception ex){
847           JOptionPane.showMessageDialog(largeView != null ?
848                                         largeView : smallView,
849                                         "Look what you've done: \n" +
850                                         ex.toString() +
851                                         "\nI told you not to do it...",
852                                         "GATE", JOptionPane.ERROR_MESSAGE);
853           ex.printStackTrace(Err.getPrintWriter());
854         }
855       }
856     }
857   }
858 
859   class SaveAction extends AbstractAction {
860     public SaveAction(){
861       super("Save");
862       putValue(SHORT_DESCRIPTION, "Save back to the datastore");
863     }
864     public void actionPerformed(ActionEvent e){
865       Runnable runnable = new Runnable(){
866         public void run(){
867           DataStore ds = ((LanguageResource)target).getDataStore();
868           if(ds != null){
869             try {
870               MainFrame.lockGUI("Saving " + ((LanguageResource)target).getName());
871               StatusListener sListener = (StatusListener)
872                                          gate.gui.MainFrame.getListeners().
873                                          get("gate.event.StatusListener");
874               if(sListener != null) sListener.statusChanged(
875                 "Saving: " + ((LanguageResource)target).getName());
876               double timeBefore = System.currentTimeMillis();
877               ((LanguageResource)
878                         target).getDataStore().sync((LanguageResource)target);
879               double timeAfter = System.currentTimeMillis();
880               if(sListener != null) sListener.statusChanged(
881                 ((LanguageResource)target).getName() + " saved in " +
882                 NumberFormat.getInstance().format((timeAfter-timeBefore)/1000)
883                 + " seconds");
884             } catch(PersistenceException pe) {
885               MainFrame.unlockGUI();
886               JOptionPane.showMessageDialog(getLargeView(),
887                                             "Save failed!\n " +
888                                             pe.toString(),
889                                             "GATE", JOptionPane.ERROR_MESSAGE);
890             } catch(SecurityException se) {
891               MainFrame.unlockGUI();
892               JOptionPane.showMessageDialog(getLargeView(),
893                                             "Save failed!\n " +
894                                             se.toString(),
895                                             "GATE", JOptionPane.ERROR_MESSAGE);
896             }finally{
897               MainFrame.unlockGUI();
898             }
899           } else {
900             JOptionPane.showMessageDialog(getLargeView(),
901                             "This resource has not been loaded from a datastore.\n"+
902                              "Please use the \"Save to\" option!\n",
903                              "GATE", JOptionPane.ERROR_MESSAGE);
904 
905           }
906         }
907       };
908       new Thread(runnable).start();
909     }//public void actionPerformed(ActionEvent e)
910   }//class SaveAction
911 
912 
913 
914   class DumpToFileAction extends AbstractAction {
915     public DumpToFileAction(){
916       super("Save application state");
917       putValue(SHORT_DESCRIPTION,
918                "Saves the data needed to recreate this application");
919     }
920 
921     public void actionPerformed(ActionEvent ae){
922       JFileChooser fileChooser = MainFrame.getFileChooser();
923 
924       fileChooser.setDialogTitle("Select a file for this resource");
925       fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
926       if (fileChooser.showSaveDialog(largeView) ==
927                                             JFileChooser.APPROVE_OPTION){
928         final File file = fileChooser.getSelectedFile();
929           Runnable runnable = new Runnable(){
930             public void run(){
931               try{
932                 gate.util.persistence.PersistenceManager.
933                                       saveObjectToFile((Resource)target, file);
934               }catch(Exception e){
935                 JOptionPane.showMessageDialog(getLargeView(),
936                                 "Error!\n"+
937                                  e.toString(),
938                                  "GATE", JOptionPane.ERROR_MESSAGE);
939                 e.printStackTrace(Err.getPrintWriter());
940               }
941             }
942           };
943           Thread thread = new Thread(runnable);
944           thread.setPriority(Thread.MIN_PRIORITY);
945           thread.start();
946       }
947     }
948 
949   }
950 
951   class SaveToAction extends AbstractAction {
952     public SaveToAction(){
953       super("Save to...");
954       putValue(SHORT_DESCRIPTION, "Save this resource to a datastore");
955     }
956 
957     public void actionPerformed(ActionEvent e) {
958       Runnable runnable = new Runnable(){
959         public void run(){
960           try {
961             DataStoreRegister dsReg = Gate.getDataStoreRegister();
962             Map dsByName =new HashMap();
963             Iterator dsIter = dsReg.iterator();
964             while(dsIter.hasNext()){
965               DataStore oneDS = (DataStore)dsIter.next();
966               String name;
967               if((name = (String)oneDS.getName()) != null){
968               } else {
969                 name  = oneDS.getStorageUrl();
970                 try {
971                   URL tempURL = new URL(name);
972                   name = tempURL.getFile();
973                 } catch (java.net.MalformedURLException ex) {
974                   throw new GateRuntimeException(
975                             );
976                 }
977               }
978               dsByName.put(name, oneDS);
979             }
980             List dsNames = new ArrayList(dsByName.keySet());
981             if(dsNames.isEmpty()){
982               JOptionPane.showMessageDialog(getLargeView(),
983                                             "There are no open datastores!\n " +
984                                             "Please open a datastore first!",
985                                             "GATE", JOptionPane.ERROR_MESSAGE);
986 
987             } else {
988               Object answer = JOptionPane.showInputDialog(
989                                   getLargeView(),
990                                   "Select the datastore",
991                                   "GATE", JOptionPane.QUESTION_MESSAGE,
992                                   null, dsNames.toArray(),
993                                   dsNames.get(0));
994               if(answer == null) return;
995               DataStore ds = (DataStore)dsByName.get(answer);
996               if (ds == null){
997                 Err.prln("The datastore does not exists. Saving procedure" +
998                                   " has FAILED! This should never happen again!");
999                 return;
1000              }// End if
1001              DataStore ownDS = ((LanguageResource)target).getDataStore();
1002              if(ds == ownDS){
1003                MainFrame.lockGUI("Saving " + ((LanguageResource)target).getName());
1004
1005                StatusListener sListener = (StatusListener)
1006                                           gate.gui.MainFrame.getListeners().
1007                                           get("gate.event.StatusListener");
1008                if(sListener != null) sListener.statusChanged(
1009                  "Saving: " + ((LanguageResource)target).getName());
1010                double timeBefore = System.currentTimeMillis();
1011                ds.sync((LanguageResource)target);
1012                double timeAfter = System.currentTimeMillis();
1013                if(sListener != null) sListener.statusChanged(
1014                  ((LanguageResource)target).getName() + " saved in " +
1015                  NumberFormat.getInstance().format((timeAfter-timeBefore)/1000)
1016                  + " seconds");
1017              }else{
1018                FeatureMap securityData = (FeatureMap)
1019                             DataStoreRegister.getSecurityData(ds);
1020                SecurityInfo si = null;
1021                //check whether the datastore supports security data
1022                //serial ones do not for example
1023                if (securityData != null) {
1024                  //first get the type of access from the user
1025                  if(!AccessRightsDialog.showDialog(window))
1026                    return;
1027                  int accessType = AccessRightsDialog.getSelectedMode();
1028                  if(accessType < 0)
1029                    return;
1030                  si = new SecurityInfo(accessType,
1031                                        (User) securityData.get("user"),
1032                                        (Group) securityData.get("group"));
1033                }//if security info
1034                StatusListener sListener = (StatusListener)
1035                                           gate.gui.MainFrame.getListeners().
1036                                           get("gate.event.StatusListener");
1037                MainFrame.lockGUI("Saving " + ((LanguageResource)target).getName());
1038
1039                if(sListener != null) sListener.statusChanged(
1040                  "Saving: " + ((LanguageResource)target).getName());
1041                double timeBefore = System.currentTimeMillis();
1042                LanguageResource lr = ds.adopt((LanguageResource)target,si);
1043                ds.sync(lr);
1044                double timeAfter = System.currentTimeMillis();
1045                if(sListener != null) sListener.statusChanged(
1046                  ((LanguageResource)target).getName() + " saved in " +
1047                  NumberFormat.getInstance().format((timeAfter-timeBefore)/1000)
1048                  + " seconds");
1049
1050                //check whether the new LR is different from the transient one and
1051                //if so, unload the transient LR, so the user realises
1052                //it is no longer valid. Don't do this in the adopt() code itself
1053                //because the batch code might wish to keep the transient
1054                //resource for some purpose.
1055                if (lr != target) {
1056                  Factory.deleteResource((LanguageResource)target);
1057                }
1058              }
1059            }
1060          } catch(PersistenceException pe) {
1061            MainFrame.unlockGUI();
1062            JOptionPane.showMessageDialog(getLargeView(),
1063                                          "Save failed!\n " +
1064                                          pe.toString(),
1065                                          "GATE", JOptionPane.ERROR_MESSAGE);
1066          }catch(gate.security.SecurityException se) {
1067            MainFrame.unlockGUI();
1068            JOptionPane.showMessageDialog(getLargeView(),
1069                                          "Save failed!\n " +
1070                                          se.toString(),
1071                                          "GATE", JOptionPane.ERROR_MESSAGE);
1072          }finally{
1073            MainFrame.unlockGUI();
1074          }
1075
1076        }
1077      };
1078      new Thread(runnable).start();
1079    }
1080  }//class SaveToAction extends AbstractAction
1081
1082  class ReloadAction extends AbstractAction {
1083    ReloadAction() {
1084      super("Reinitialise");
1085      putValue(SHORT_DESCRIPTION, "Reloads this resource");
1086    }
1087
1088    public void actionPerformed(ActionEvent e) {
1089      Runnable runnable = new Runnable(){
1090        public void run(){
1091          if(!(target instanceof ProcessingResource)) return;
1092          try{
1093            long startTime = System.currentTimeMillis();
1094            fireStatusChanged("Reinitialising " +
1095                               target.getName());
1096            Map listeners = new HashMap();
1097            StatusListener sListener = new StatusListener(){
1098                                        public void statusChanged(String text){
1099                                          fireStatusChanged(text);
1100                                        }
1101                                       };
1102            listeners.put("gate.event.StatusListener", sListener);
1103
1104            ProgressListener pListener =
1105                new ProgressListener(){
1106                  public void progressChanged(int value){
1107                    fireProgressChanged(value);
1108                  }
1109                  public void processFinished(){
1110                    fireProcessFinished();
1111                  }
1112                };
1113            listeners.put("gate.event.ProgressListener", pListener);
1114
1115            ProcessingResource res = (ProcessingResource)target;
1116            try{
1117              AbstractResource.setResourceListeners(res, listeners);
1118            }catch (Exception e){
1119              e.printStackTrace(Err.getPrintWriter());
1120            }
1121            //show the progress indicator
1122            fireProgressChanged(0);
1123            //the actual reinitialisation
1124            res.reInit();
1125            try{
1126              AbstractResource.removeResourceListeners(res, listeners);
1127            }catch (Exception e){
1128              e.printStackTrace(Err.getPrintWriter());
1129            }
1130            long endTime = System.currentTimeMillis();
1131            fireStatusChanged(target.getName() +
1132                              " reinitialised in " +
1133                              NumberFormat.getInstance().format(
1134                              (double)(endTime - startTime) / 1000) + " seconds");
1135            fireProcessFinished();
1136          }catch(ResourceInstantiationException rie){
1137            fireStatusChanged("reinitialisation failed");
1138            rie.printStackTrace(Err.getPrintWriter());
1139            JOptionPane.showMessageDialog(getLargeView(),
1140                                          "Reload failed!\n " +
1141                                          "See \"Messages\" tab for details!",
1142                                          "GATE", JOptionPane.ERROR_MESSAGE);
1143            fireProcessFinished();
1144          }
1145        }//public void run()
1146      };
1147      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1148                                 runnable,
1149                                 "DefaultResourceHandle1");
1150      thread.setPriority(Thread.MIN_PRIORITY);
1151      thread.start();
1152    }//public void actionPerformed(ActionEvent e)
1153
1154  }//class ReloadAction
1155
1156  class PopulateCorpusAction extends AbstractAction {
1157    PopulateCorpusAction() {
1158      super("Populate");
1159      putValue(SHORT_DESCRIPTION,
1160               "Fills this corpus with documents from a directory");
1161    }
1162
1163    public void actionPerformed(ActionEvent e) {
1164      Runnable runnable = new Runnable(){
1165        public void run(){
1166          corpusFiller.setExtensions(new ArrayList());
1167          corpusFiller.setEncoding("");
1168          boolean answer = OkCancelDialog.showDialog(
1169                                  getLargeView(),
1170                                  corpusFiller,
1171                                  "Select a directory and allowed extensions");
1172          if(answer){
1173            long startTime = System.currentTimeMillis();
1174            URL url = null;
1175            try{
1176              url = new URL(corpusFiller.getUrlString());
1177              java.util.List extensions = corpusFiller.getExtensions();
1178              ExtensionFileFilter filter = null;
1179              if(extensions == null || extensions.isEmpty()) filter = null;
1180              else{
1181                filter = new ExtensionFileFilter();
1182                Iterator extIter = corpusFiller.getExtensions().iterator();
1183                while(extIter.hasNext()){
1184                  filter.addExtension((String)extIter.next());
1185                }
1186              }
1187              ((Corpus)target).populate(url, filter,
1188                                        corpusFiller.getEncoding(),
1189                                        corpusFiller.isRecurseDirectories());
1190              long endTime = System.currentTimeMillis();
1191              fireStatusChanged("Corpus populated in " +
1192                      NumberFormat.getInstance().
1193                      format((double)(endTime - startTime) / 1000) +
1194                      " seconds!");
1195
1196            }catch(MalformedURLException mue){
1197              JOptionPane.showMessageDialog(getLargeView(),
1198                                            "Invalid URL!\n " +
1199                                            "See \"Messages\" tab for details!",
1200                                            "GATE", JOptionPane.ERROR_MESSAGE);
1201              mue.printStackTrace(Err.getPrintWriter());
1202            }catch(IOException ioe){
1203              JOptionPane.showMessageDialog(getLargeView(),
1204                                            "I/O error!\n " +
1205                                            "See \"Messages\" tab for details!",
1206                                            "GATE", JOptionPane.ERROR_MESSAGE);
1207              ioe.printStackTrace(Err.getPrintWriter());
1208            }catch(ResourceInstantiationException rie){
1209              JOptionPane.showMessageDialog(getLargeView(),
1210                                            "Could not create document!\n " +
1211                                            "See \"Messages\" tab for details!",
1212                                            "GATE", JOptionPane.ERROR_MESSAGE);
1213              rie.printStackTrace(Err.getPrintWriter());
1214            }
1215          }
1216        }
1217      };
1218      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1219                                 runnable);
1220      thread.setPriority(Thread.MIN_PRIORITY);
1221      thread.start();
1222    }
1223  }
1224
1225  class CreateIndexAction1 extends AbstractAction {
1226    CreateIndexAction1() {
1227      super("Create Index");
1228      putValue(SHORT_DESCRIPTION,
1229               "Create index with documents from a corpus");
1230    }
1231
1232    public void actionPerformed(ActionEvent e) {
1233      CreateIndexDialog cid = null;
1234      if (getWindow() instanceof Frame){
1235        cid = new CreateIndexDialog((Frame) getWindow(), (IndexedCorpus) target);
1236      }
1237      if (getWindow() instanceof Dialog){
1238        cid = new CreateIndexDialog((Dialog) getWindow(), (IndexedCorpus) target);
1239      }
1240      cid.setVisible(true);
1241    }
1242  }
1243
1244  class CreateIndexAction extends AbstractAction {
1245    CreateIndexAction() {
1246      super("Index corpus");
1247      putValue(SHORT_DESCRIPTION,
1248               "Create index with documents from the corpus");
1249      createIndexGui = new CreateIndexGUI();
1250    }
1251
1252    public void actionPerformed(ActionEvent e) {
1253      boolean ok = OkCancelDialog.showDialog(largeView,
1254                                             createIndexGui,
1255                                             "Index \"" + target.getName() +
1256                                             "\" corpus");
1257      if(ok){
1258        DefaultIndexDefinition did = new DefaultIndexDefinition();
1259        IREngine engine = createIndexGui.getIREngine();
1260        did.setIrEngineClassName(engine.getClass().getName());
1261
1262        did.setIndexLocation(createIndexGui.getIndexLocation().toString());
1263
1264        //add the content if wanted
1265        if(createIndexGui.getUseDocumentContent()){
1266          did.addIndexField(new IndexField("body",
1267                                           new DocumentContentReader(),
1268                                           false));
1269        }
1270        //add all the features
1271        Iterator featIter = createIndexGui.getFeaturesList().iterator();
1272        while(featIter.hasNext()){
1273          String featureName = (String)featIter.next();
1274          did.addIndexField(new IndexField(featureName,
1275                                           new FeatureReader(featureName),
1276                                           false));
1277        }
1278
1279        ((IndexedCorpus)target).setIndexDefinition(did);
1280
1281        Thread thread = new Thread(new Runnable(){
1282          public void run(){
1283            try {
1284              fireProgressChanged(1);
1285              fireStatusChanged("Indexing corpus...");
1286              long start = System.currentTimeMillis();
1287              ((IndexedCorpus)target).getIndexManager().deleteIndex();
1288              fireProgressChanged(10);
1289              ((IndexedCorpus)target).getIndexManager().createIndex();
1290              fireProgressChanged(100);
1291              fireProcessFinished();
1292              fireStatusChanged(
1293                "Corpus indexed in " + NumberFormat.getInstance().format(
1294                (double)(System.currentTimeMillis() - start) / 1000) +
1295                " seconds");
1296            } catch (IndexException ie){
1297              JOptionPane.showMessageDialog(getLargeView() != null ?
1298                                            getLargeView() : getSmallView(),
1299                                            "Could not create index!\n " +
1300                                            "See \"Messages\" tab for details!",
1301                                            "GATE", JOptionPane.ERROR_MESSAGE);
1302              ie.printStackTrace(Err.getPrintWriter());
1303            }finally{
1304              fireProcessFinished();
1305            }
1306          }
1307        });
1308        thread.setPriority(Thread.MIN_PRIORITY);
1309        thread.start();
1310      }
1311    }
1312    CreateIndexGUI createIndexGui;
1313  }
1314
1315  class OptimizeIndexAction extends AbstractAction {
1316    OptimizeIndexAction() {
1317      super("Optimize Index");
1318      putValue(SHORT_DESCRIPTION,
1319               "Optimize existing index");
1320    }
1321
1322    public boolean isEnabled(){
1323      return ((IndexedCorpus)target).getIndexDefinition() != null;
1324    }
1325
1326    public void actionPerformed(ActionEvent e) {
1327      IndexedCorpus ic = (IndexedCorpus) target;
1328      Thread thread = new Thread(new Runnable(){
1329        public void run(){
1330          try{
1331            fireProgressChanged(1);
1332            fireStatusChanged("Optimising index...");
1333            long start  = System.currentTimeMillis();
1334            ((IndexedCorpus)target).getIndexManager().optimizeIndex();
1335            fireStatusChanged(
1336              "Index optimised in " + NumberFormat.getInstance().format(
1337              (double)(System.currentTimeMillis() - start) / 1000) +
1338              " seconds");
1339            fireProcessFinished();
1340          }catch(IndexException ie){
1341            JOptionPane.showMessageDialog(getLargeView() != null ?
1342                                          getLargeView() : getSmallView(),
1343                                          "Errors during optimisation!",
1344                                          "GATE",
1345                                          JOptionPane.PLAIN_MESSAGE);
1346            ie.printStackTrace(Err.getPrintWriter());
1347          }finally{
1348            fireProcessFinished();
1349          }
1350        }
1351      });
1352      thread.setPriority(Thread.MIN_PRIORITY);
1353      thread.start();
1354    }
1355  }
1356
1357  class DeleteIndexAction extends AbstractAction {
1358    DeleteIndexAction() {
1359      super("Delete Index");
1360      putValue(SHORT_DESCRIPTION,
1361               "Delete existing index");
1362    }
1363
1364    public boolean isEnabled(){
1365      return ((IndexedCorpus)target).getIndexDefinition() != null;
1366    }
1367
1368    public void actionPerformed(ActionEvent e) {
1369      int answer = JOptionPane.showOptionDialog(
1370              getLargeView() != null ? getLargeView() : getSmallView(),
1371              "Do you want to delete index?", "Gate",
1372              JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
1373              null, null, null);
1374      if (answer == JOptionPane.YES_OPTION) {
1375        try {
1376          IndexedCorpus ic = (IndexedCorpus) target;
1377          if (ic.getIndexManager() != null){
1378            ic.getIndexManager().deleteIndex();
1379            ic.getFeatures().remove(GateConstants.
1380                                    CORPUS_INDEX_DEFINITION_FEATURE_KEY);
1381          } else {
1382            JOptionPane.showMessageDialog(getLargeView() != null ?
1383                                     getLargeView() :
1384                                     getSmallView(),
1385                                     "There is no index to delete!",
1386                                     "GATE", JOptionPane.PLAIN_MESSAGE);
1387          }
1388        } catch (gate.creole.ir.IndexException ie) {
1389          ie.printStackTrace();
1390        }
1391      }
1392    }
1393  }
1394
1395  /**
1396   * Releases the memory, removes the listeners, cleans up.
1397   * Will get called when the target resource is unloaded from the system
1398   */
1399  public void cleanup(){
1400    //delete all the VRs that were created
1401    if(largeView != null){
1402      if(largeView instanceof VisualResource){
1403        //we only had a view so no tabbed pane was used
1404        Factory.deleteResource((VisualResource)largeView);
1405      }else{
1406        Component vrs[] = ((JTabbedPane)largeView).getComponents();
1407        for(int i = 0; i < vrs.length; i++){
1408          if(vrs[i] instanceof VisualResource){
1409            Factory.deleteResource((VisualResource)vrs[i]);
1410          }
1411        }
1412      }
1413    }
1414
1415    if(smallView != null){
1416      if(smallView instanceof VisualResource){
1417        //we only had a view so no tabbed pane was used
1418        Factory.deleteResource((VisualResource)smallView);
1419      }else{
1420        Component vrs[] = ((JTabbedPane)smallView).getComponents();
1421        for(int i = 0; i < vrs.length; i++){
1422          if(vrs[i] instanceof VisualResource){
1423            Factory.deleteResource((VisualResource)vrs[i]);
1424          }
1425        }
1426      }
1427    }
1428
1429    Gate.getCreoleRegister().removeCreoleListener(this);
1430    target = null;
1431  }
1432
1433  class ProxyStatusListener implements StatusListener{
1434    public void statusChanged(String text){
1435      fireStatusChanged(text);
1436    }
1437  }
1438
1439  protected void fireProgressChanged(int e) {
1440    if (progressListeners != null) {
1441      Vector listeners = progressListeners;
1442      int count = listeners.size();
1443      for (int i = 0; i < count; i++) {
1444        ((ProgressListener) listeners.elementAt(i)).progressChanged(e);
1445      }
1446    }
1447  }//protected void fireProgressChanged(int e)
1448
1449  protected void fireProcessFinished() {
1450    if (progressListeners != null) {
1451      Vector listeners = progressListeners;
1452      int count = listeners.size();
1453      for (int i = 0; i < count; i++) {
1454        ((ProgressListener) listeners.elementAt(i)).processFinished();
1455      }
1456    }
1457  }//protected void fireProcessFinished()
1458
1459  public synchronized void removeStatusListener(StatusListener l) {
1460    if (statusListeners != null && statusListeners.contains(l)) {
1461      Vector v = (Vector) statusListeners.clone();
1462      v.removeElement(l);
1463      statusListeners = v;
1464    }
1465  }//public synchronized void removeStatusListener(StatusListener l)
1466
1467  public synchronized void addStatusListener(StatusListener l) {
1468    Vector v = statusListeners == null ? new Vector(2) : (Vector) statusListeners.clone();
1469    if (!v.contains(l)) {
1470      v.addElement(l);
1471      statusListeners = v;
1472    }
1473  }//public synchronized void addStatusListener(StatusListener l)
1474
1475  protected void fireStatusChanged(String e) {
1476    if (statusListeners != null) {
1477      Vector listeners = statusListeners;
1478      int count = listeners.size();
1479      for (int i = 0; i < count; i++) {
1480        ((StatusListener) listeners.elementAt(i)).statusChanged(e);
1481      }
1482    }
1483  }
1484
1485  public void statusChanged(String e) {
1486    fireStatusChanged(e);
1487  }
1488  public void progressChanged(int e) {
1489    fireProgressChanged(e);
1490  }
1491  public void processFinished() {
1492    fireProcessFinished();
1493  }
1494  public Window getWindow() {
1495    return window;
1496  }
1497
1498  public void resourceLoaded(CreoleEvent e) {
1499  }
1500
1501  public void resourceUnloaded(CreoleEvent e) {
1502  }
1503
1504  public void resourceRenamed(Resource resource, String oldName,
1505                              String newName){
1506    if(target == resource) title = target.getName();
1507  }
1508
1509  public void datastoreOpened(CreoleEvent e) {
1510  }
1511
1512  public void datastoreCreated(CreoleEvent e) {
1513  }
1514
1515  public void datastoreClosed(CreoleEvent e) {
1516    if(getTarget() == e.getDatastore()) cleanup();
1517  }
1518}//class DefaultResourceHandle
1519