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