NameBearerHandle.java
0001 /*
0002  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
0003  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
0004  *
0005  *  This file is part of GATE (see http://gate.ac.uk/), and is free
0006  *  software, licenced under the GNU Library General Public License,
0007  *  Version 2, June 1991 (in the distribution as file licence.html,
0008  *  and also available at http://gate.ac.uk/gate/licence.html).
0009  *
0010  *  Valentin Tablan 23/01/2001
0011  *
0012  *  $Id: NameBearerHandle.java 13605 2011-04-05 12:04:59Z ian_roberts $
0013  *
0014  */
0015 
0016 package gate.gui;
0017 
0018 import gate.Controller;
0019 import gate.Corpus;
0020 import gate.CorpusController;
0021 import gate.DataStore;
0022 import gate.DataStoreRegister;
0023 import gate.Document;
0024 import gate.Executable;
0025 import gate.Factory;
0026 import gate.FeatureMap;
0027 import gate.Gate;
0028 import gate.GateConstants;
0029 import gate.LanguageResource;
0030 import gate.ProcessingResource;
0031 import gate.Resource;
0032 import gate.VisualResource;
0033 import gate.corpora.DocumentStaxUtils;
0034 import gate.creole.AbstractResource;
0035 import gate.creole.AnnotationSchema;
0036 import gate.creole.ConditionalController;
0037 import gate.creole.ResourceData;
0038 import gate.creole.ResourceInstantiationException;
0039 import gate.creole.ir.DefaultIndexDefinition;
0040 import gate.creole.ir.DocumentContentReader;
0041 import gate.creole.ir.FeatureReader;
0042 import gate.creole.ir.IREngine;
0043 import gate.creole.ir.IndexException;
0044 import gate.creole.ir.IndexField;
0045 import gate.creole.ir.IndexedCorpus;
0046 import gate.event.CreoleEvent;
0047 import gate.event.CreoleListener;
0048 import gate.event.ProgressListener;
0049 import gate.event.StatusListener;
0050 import gate.gui.teamware.InputOutputAnnotationSetsDialog;
0051 import gate.persist.LuceneDataStoreImpl;
0052 import gate.persist.PersistenceException;
0053 import gate.security.Group;
0054 import gate.security.SecurityException;
0055 import gate.security.SecurityInfo;
0056 import gate.security.User;
0057 import gate.swing.XJFileChooser;
0058 import gate.swing.XJMenuItem;
0059 import gate.swing.XJPopupMenu;
0060 import gate.util.Err;
0061 import gate.util.ExtensionFileFilter;
0062 import gate.util.Files;
0063 import gate.util.GateRuntimeException;
0064 import gate.util.InvalidOffsetException;
0065 import gate.util.NameBearer;
0066 import gate.util.Out;
0067 import gate.util.ant.packager.PackageGappTask;
0068 
0069 import java.awt.Component;
0070 import java.awt.Dialog;
0071 import java.awt.Frame;
0072 import java.awt.Window;
0073 import java.awt.event.ActionEvent;
0074 import java.io.File;
0075 import java.io.FileOutputStream;
0076 import java.io.IOException;
0077 import java.io.OutputStreamWriter;
0078 import java.net.MalformedURLException;
0079 import java.net.URISyntaxException;
0080 import java.net.URL;
0081 import java.text.NumberFormat;
0082 import java.util.ArrayList;
0083 import java.util.Collections;
0084 import java.util.EventListener;
0085 import java.util.HashMap;
0086 import java.util.Iterator;
0087 import java.util.List;
0088 import java.util.Map;
0089 import java.util.Set;
0090 import java.util.Vector;
0091 
0092 import javax.swing.AbstractAction;
0093 import javax.swing.Action;
0094 import javax.swing.Icon;
0095 import javax.swing.JComponent;
0096 import javax.swing.JFileChooser;
0097 import javax.swing.JMenuItem;
0098 import javax.swing.JOptionPane;
0099 import javax.swing.JPopupMenu;
0100 import javax.swing.JTabbedPane;
0101 import javax.swing.KeyStroke;
0102 
0103 import org.apache.log4j.Logger;
0104 import org.apache.tools.ant.BuildEvent;
0105 import org.apache.tools.ant.BuildException;
0106 import org.apache.tools.ant.BuildListener;
0107 import org.apache.tools.ant.Project;
0108 import org.apache.tools.ant.taskdefs.Delete;
0109 import org.apache.tools.ant.taskdefs.Zip;
0110 import org.apache.tools.ant.types.FileSet;
0111 
0112 /**
0113  * Class used to store the GUI information about an open entity
0114  * (resource, controller, datastore). Such information will include icon
0115  * to be used for tree components, popup menu for right click events,
0116  * large and small views, etc.
0117  */
0118 public class NameBearerHandle implements Handle, StatusListener,
0119                              ProgressListener, CreoleListener {
0120 
0121   public NameBearerHandle(NameBearer target, Window window) {
0122     this.target = target;
0123     this.window = window;
0124     actionPublishers = new ArrayList<ActionsPublisher>();
0125 
0126     sListenerProxy = new ProxyStatusListener();
0127     String iconName = null;
0128     if(target instanceof Resource) {
0129       rData = Gate.getCreoleRegister().get(target.getClass().getName());
0130       if(rData != null) {
0131         iconName = rData.getIcon();
0132         if(iconName == null) {
0133           if(target instanceof Controller)
0134             iconName = "application";
0135           else if(target instanceof LanguageResource)
0136             iconName = "lr";
0137           else if(target instanceof ProcessingResourceiconName = "pr";
0138         }
0139         if(target instanceof Controller && target.getName().startsWith("ANNIE"))
0140           iconName = "annie-application";
0141         tooltipText = "<HTML> <b>" + rData.getComment() "</b><br>(<i>"
0142                 + rData.getClassName() "</i>)</HTML>";
0143       }
0144       else {
0145         iconName = "lr";
0146       }
0147     }
0148     else if(target instanceof DataStore) {
0149       iconName = ((DataStore)target).getIconName();
0150       tooltipText = ((DataStore)target).getComment();
0151     }
0152 
0153     this.icon = MainFrame.getIcon(iconName);
0154 
0155     Gate.getCreoleRegister().addCreoleListener(this);
0156 
0157     if(target instanceof ActionsPublisher)
0158       actionPublishers.add((ActionsPublisher)target);
0159 
0160     buildStaticPopupItems();
0161 
0162     viewsBuilt = false;
0163   }// public DefaultResourceHandle(FeatureBearer res)
0164 
0165   public Icon getIcon() {
0166     return icon;
0167   }
0168 
0169   public void setIcon(Icon icon) {
0170     this.icon = icon;
0171   }
0172 
0173   public String getTitle() {
0174     return target == null null : target.getName();
0175   }
0176 
0177   /**
0178    * Returns <tt>true</tt> if the views have already been built for this
0179    * handle.
0180    
0181    @return <tt>boolean</tt> value.
0182    */
0183   public boolean viewsBuilt() {
0184     return viewsBuilt;
0185   }
0186 
0187   /**
0188    * Returns a GUI component to be used as a small viewer/editor, e.g.
0189    * below the main tree in the Gate GUI for the selected resource
0190    */
0191   public JComponent getSmallView() {
0192     if(!viewsBuiltbuildViews();
0193     return smallView;
0194   }
0195 
0196   /**
0197    * Returns the large view for this resource. This view will go into
0198    * the main display area.
0199    */
0200   public JComponent getLargeView() {
0201     if(!viewsBuiltbuildViews();
0202     return largeView;
0203   }
0204 
0205   public JPopupMenu getPopup() {
0206     JPopupMenu popup = new XJPopupMenu();
0207     // first add the static items
0208     Iterator itemIter = staticPopupItems.iterator();
0209     while(itemIter.hasNext()) {
0210       JMenuItem anItem = (JMenuItem)itemIter.next();
0211       if(anItem == null)
0212         popup.addSeparator();
0213       else popup.add(anItem);
0214     }
0215 
0216     // next add the dynamic list from the target and its editors
0217     Iterator publishersIter = actionPublishers.iterator();
0218     while(publishersIter.hasNext()) {
0219       ActionsPublisher aPublisher = (ActionsPublisher)publishersIter.next();
0220       if(aPublisher.getActions() != null) {
0221         Iterator actionIter = aPublisher.getActions().iterator();
0222         while(actionIter.hasNext()) {
0223           Action anAction = (Action)actionIter.next();
0224           if(anAction == null)
0225             popup.addSeparator();
0226           else {
0227             popup.add(new XJMenuItem(anAction, sListenerProxy));
0228           }
0229         }
0230       }
0231     }
0232 
0233     return popup;
0234   }
0235 
0236   public String getTooltipText() {
0237     return tooltipText;
0238   }
0239 
0240   public void setTooltipText(String text) {
0241     this.tooltipText = text;
0242   }
0243 
0244   public Object getTarget() {
0245     return target;
0246   }
0247 
0248   public Action getCloseAction() {
0249     return new CloseAction();
0250   }
0251 
0252   public Action getCloseRecursivelyAction() {
0253     return new CloseRecursivelyAction();
0254   }
0255 
0256   /** Fill HMM Save and Save As... actions */
0257   private void fillHMMActions(List<XJMenuItem> popupItems) {
0258     Action action;
0259 
0260     com.ontotext.gate.hmm.agent.AlternativeHMMAgent hmmPR = (com.ontotext.gate.hmm.agent.AlternativeHMMAgent)target;
0261 
0262     popupItems.add(null);
0263     action = new com.ontotext.gate.hmm.agent.SaveAction(hmmPR);
0264     action.putValue(Action.SHORT_DESCRIPTION,
0265             "Save trained HMM model into PR URL file");
0266     // Add Save trained HMM model action
0267     popupItems.add(new XJMenuItem(action, sListenerProxy));
0268 
0269     action = new com.ontotext.gate.hmm.agent.SaveAsAction(hmmPR);
0270     action.putValue(Action.SHORT_DESCRIPTION,
0271             "Save trained HMM model into new file");
0272     // Add Save As... trained HMM model action
0273     popupItems.add(new XJMenuItem(action, sListenerProxy));
0274   // fillHMMActions(gate.gui.ProtegeWrapper protege)
0275 
0276   // protected JPopupMenu buildPopup(){
0277   // //build the popup
0278   // JPopupMenu popup = new JPopupMenu();
0279   // XJMenuItem closeItem = new XJMenuItem(new CloseAction(),
0280   // sListenerProxy);
0281   // closeItem.setAccelerator(KeyStroke.getKeyStroke(
0282   // KeyEvent.VK_F4, ActionEvent.CTRL_MASK));
0283   // popup.add(closeItem);
0284   //
0285   // if(target instanceof ProcessingResource){
0286   // popup.addSeparator();
0287   // popup.add(new XJMenuItem(new ReloadAction(), sListenerProxy));
0288   // if(target instanceof gate.ml.DataCollector){
0289   // popup.add(new DumpArffAction());
0290   // }
0291   // if(target instanceof
0292   // com.ontotext.gate.hmm.agent.AlternativeHMMAgent) {
0293   // fillHMMActions(popup);
0294   // } // if
0295   // }else if(target instanceof LanguageResource) {
0296   // //Language Resources
0297   // popup.addSeparator();
0298   // popup.add(new XJMenuItem(new SaveAction(), sListenerProxy));
0299   // popup.add(new XJMenuItem(new SaveToAction(), sListenerProxy));
0300   // if(target instanceof gate.TextualDocument){
0301   // XJMenuItem saveAsXmlItem =
0302   // new XJMenuItem(new SaveAsXmlAction(), sListenerProxy);
0303   // saveAsXmlItem.setAccelerator(KeyStroke.getKeyStroke(
0304   // KeyEvent.VK_X, ActionEvent.CTRL_MASK));
0305   //
0306   // popup.add(saveAsXmlItem);
0307   // XJMenuItem savePreserveFormatItem =
0308   // new XJMenuItem(new DumpPreserveFormatAction(),
0309   // sListenerProxy);
0310   // popup.add(savePreserveFormatItem);
0311   // }else if(target instanceof Corpus){
0312   // popup.addSeparator();
0313   // corpusFiller = new CorpusFillerComponent();
0314   // popup.add(new XJMenuItem(new PopulateCorpusAction(),
0315   // sListenerProxy));
0316   // popup.addSeparator();
0317   // popup.add(new XJMenuItem(new SaveCorpusAsXmlAction(false),
0318   // sListenerProxy));
0319   // popup.add(new XJMenuItem(new SaveCorpusAsXmlAction(true),
0320   // sListenerProxy));
0321   // if (target instanceof IndexedCorpus){
0322   // popup.addSeparator();
0323   // popup.add(new XJMenuItem(new CreateIndexAction(), sListenerProxy));
0324   // popup.add(new XJMenuItem(new OptimizeIndexAction(),
0325   // sListenerProxy));
0326   // popup.add(new XJMenuItem(new DeleteIndexAction(), sListenerProxy));
0327   // }
0328   // }
0329   // if (target instanceof gate.creole.ProtegeProjectName){
0330   // fillProtegeActions(popup);
0331   // }// End if
0332   // }else if(target instanceof Controller){
0333   // //Applications
0334   // popup.addSeparator();
0335   // popup.add(new XJMenuItem(new DumpToFileAction(), sListenerProxy));
0336   // }
0337   //
0338   // //add the custom actions from the resource if any are provided
0339   // if(target instanceof ActionsPublisher){
0340   // Iterator actionsIter =
0341   // ((ActionsPublisher)target).getActions().iterator();
0342   // while(actionsIter.hasNext()){
0343   // Action anAction = (Action)actionsIter.next();
0344   // if(anAction == null) popup.addSeparator();
0345   // else{
0346   // if(window instanceof StatusListener)
0347   // popup.add(new XJMenuItem(anAction, (StatusListener)window));
0348   // else popup.add(anAction);
0349   // }
0350   // }
0351   // }
0352   // return popup;
0353   // }
0354 
0355   protected void buildStaticPopupItems() {
0356     // build the static part of the popup
0357     staticPopupItems = new ArrayList<XJMenuItem>();
0358 
0359     if(target instanceof ProcessingResource && !(target instanceof Controller)) {
0360       // actions for PRs (but not Controllers)
0361       staticPopupItems.add(null);
0362       staticPopupItems.add(new XJMenuItem(new ReloadAction(), sListenerProxy));
0363       if(target instanceof com.ontotext.gate.hmm.agent.AlternativeHMMAgent) {
0364         fillHMMActions(staticPopupItems);
0365       }
0366     }
0367     else if(target instanceof LanguageResource) {
0368       // Language Resources
0369       staticPopupItems.add(null);
0370       if(target instanceof Document) {
0371         staticPopupItems.add(new XJMenuItem(new CreateCorpusForDocAction(),
0372                 sListenerProxy));
0373       }
0374       if(target instanceof gate.TextualDocument) {
0375         XJMenuItem saveAsXmlItem = new XJMenuItem(new SaveAsXmlAction(),
0376                 sListenerProxy);
0377         staticPopupItems.add(null);
0378         staticPopupItems.add(saveAsXmlItem);
0379       }
0380       else if(target instanceof Corpus) {
0381         corpusFiller = new CorpusFillerComponent();
0382         scfInputDialog = new SingleConcatenatedFileInputDialog();
0383         staticPopupItems.add(new XJMenuItem(new PopulateCorpusAction(),
0384                 sListenerProxy));
0385         staticPopupItems.add(new XJMenuItem(
0386                 new PopulateCorpusFromSingleConcatenatedFileAction(),
0387                 sListenerProxy));
0388         staticPopupItems.add(null);
0389         staticPopupItems.add(new XJMenuItem(new SaveCorpusAsXmlAction(false),
0390                 sListenerProxy));
0391         // staticPopupItems.add(new XJMenuItem(new
0392         // SaveCorpusAsXmlAction(true), sListenerProxy));
0393         if(target instanceof IndexedCorpus) {
0394           IndexedCorpus ic = (IndexedCorpus)target;
0395           if(ic.getDataStore() != null
0396                   && ic.getDataStore() instanceof LuceneDataStoreImpl) {
0397             // do nothing
0398           }
0399           else {
0400             staticPopupItems.add(new XJMenuItem(new CreateIndexAction(),
0401                     sListenerProxy));
0402             staticPopupItems.add(new XJMenuItem(new OptimizeIndexAction(),
0403                     sListenerProxy));
0404             staticPopupItems.add(new XJMenuItem(new DeleteIndexAction(),
0405                     sListenerProxy));
0406           }
0407         }
0408       }
0409       if(((LanguageResource)target).getDataStore() != null) {
0410         // this item can be used only if the resource belongs to a
0411         // datastore
0412         staticPopupItems.add(new XJMenuItem(new SaveAction(), sListenerProxy));
0413       }
0414       if(!(target instanceof AnnotationSchema)) {
0415         staticPopupItems
0416                 .add(new XJMenuItem(new SaveToAction(), sListenerProxy));
0417       }
0418     }
0419 
0420     if(target instanceof Controller) {
0421       // Applications
0422       staticPopupItems.add(null);
0423       staticPopupItems.add(new XJMenuItem(new DumpToFileAction(),
0424               sListenerProxy));
0425       staticPopupItems.add(new XJMenuItem(new ExportApplicationAction(),
0426               sListenerProxy));
0427     }
0428   }
0429 
0430   protected void buildViews() {
0431     viewsBuilt = true;
0432     fireStatusChanged("Building views...");
0433 
0434     // build the large views
0435     List largeViewNames = Gate.getCreoleRegister().getLargeVRsForResource(
0436             target.getClass().getName());
0437     if(largeViewNames != null && !largeViewNames.isEmpty()) {
0438       largeView = new JTabbedPane(JTabbedPane.BOTTOM);
0439       Iterator classNameIter = largeViewNames.iterator();
0440       while(classNameIter.hasNext()) {
0441         try {
0442           String className = (String)classNameIter.next();
0443           ResourceData rData = (ResourceData)Gate.getCreoleRegister().get(
0444                   className);
0445           FeatureMap params = Factory.newFeatureMap();
0446           FeatureMap features = Factory.newFeatureMap();
0447           Gate.setHiddenAttribute(features, true);
0448           VisualResource view = (VisualResource)Factory.createResource(
0449                   className, params, features);
0450           view.setTarget(target);
0451           view.setHandle(this);
0452           ((JTabbedPane)largeView).add((Component)view, rData.getName());
0453           // if view provide actions, add it to the list of action
0454           // puiblishers
0455           if(view instanceof ActionsPublisher)
0456             actionPublishers.add((ActionsPublisher)view);
0457         }
0458         catch(ResourceInstantiationException rie) {
0459           rie.printStackTrace(Err.getPrintWriter());
0460         }
0461       }
0462       if(largeViewNames.size() == 1) {
0463         largeView = (JComponent)((JTabbedPane)largeView).getComponentAt(0);
0464       }
0465       else {
0466         ((JTabbedPane)largeView).setSelectedIndex(0);
0467       }
0468     }
0469 
0470     // build the small views
0471     List smallViewNames = Gate.getCreoleRegister().getSmallVRsForResource(
0472             target.getClass().getName());
0473     if(smallViewNames != null && !smallViewNames.isEmpty()) {
0474       smallView = new JTabbedPane(JTabbedPane.BOTTOM);
0475       Iterator classNameIter = smallViewNames.iterator();
0476       while(classNameIter.hasNext()) {
0477         try {
0478           String className = (String)classNameIter.next();
0479           ResourceData rData = (ResourceData)Gate.getCreoleRegister().get(
0480                   className);
0481           FeatureMap params = Factory.newFeatureMap();
0482           FeatureMap features = Factory.newFeatureMap();
0483           Gate.setHiddenAttribute(features, true);
0484           VisualResource view = (VisualResource)Factory.createResource(
0485                   className, params, features);
0486           view.setTarget(target);
0487           view.setHandle(this);
0488           ((JTabbedPane)smallView).add((Component)view, rData.getName());
0489           if(view instanceof ActionsPublisher)
0490             actionPublishers.add((ActionsPublisher)view);
0491         }
0492         catch(ResourceInstantiationException rie) {
0493           rie.printStackTrace(Err.getPrintWriter());
0494         }
0495       }
0496       if(smallViewNames.size() == 1) {
0497         smallView = (JComponent)((JTabbedPane)smallView).getComponentAt(0);
0498       }
0499       else {
0500         ((JTabbedPane)smallView).setSelectedIndex(0);
0501       }
0502     }
0503     fireStatusChanged("Views built!");
0504 
0505     // Add the CTRL +F4 key & action combination to the resource
0506     JComponent largeView = this.getLargeView();
0507     if(largeView != null) {
0508       largeView.getActionMap().put("Close resource"new CloseAction());
0509       if(target instanceof Controller) {
0510         largeView.getActionMap().put("Close recursively",
0511                 new CloseRecursivelyAction());
0512       }
0513       if(target instanceof gate.TextualDocument) {
0514         largeView.getActionMap().put("Save As XML"new SaveAsXmlAction());
0515       }// End if
0516     }// End if
0517   }// protected void buildViews
0518 
0519   public String toString() {
0520     return getTitle();
0521   }
0522 
0523   @SuppressWarnings("unchecked")
0524   public synchronized void removeProgressListener(ProgressListener l) {
0525     if(progressListeners != null && progressListeners.contains(l)) {
0526       Vector<ProgressListener> v = (Vector<ProgressListener>)progressListeners
0527               .clone();
0528       v.removeElement(l);
0529       progressListeners = v;
0530     }
0531   }// public synchronized void removeProgressListener(ProgressListener
0532 
0533   // l)
0534 
0535   @SuppressWarnings("unchecked")
0536   public synchronized void addProgressListener(ProgressListener l) {
0537     Vector<ProgressListener> v = progressListeners == null
0538             new Vector<ProgressListener>(2)
0539             (Vector<ProgressListener>)progressListeners.clone();
0540     if(!v.contains(l)) {
0541       v.addElement(l);
0542       progressListeners = v;
0543     }
0544   }// public synchronized void addProgressListener(ProgressListener l)
0545 
0546   String tooltipText;
0547 
0548   NameBearer target;
0549 
0550   /**
0551    * Stores all the action providers for this resource. They will be
0552    * questioned when the getPopup() method is called.
0553    */
0554   protected List<ActionsPublisher> actionPublishers;
0555 
0556   /**
0557    * A list of menu items that constitute the static part of the popup.
0558    * Null values are used for separators.
0559    */
0560   protected List<XJMenuItem> staticPopupItems;
0561 
0562   /**
0563    * The top level GUI component this handle belongs to.
0564    */
0565   Window window;
0566 
0567   ResourceData rData;
0568 
0569   Icon icon;
0570 
0571   JComponent smallView;
0572 
0573   JComponent largeView;
0574 
0575   protected boolean viewsBuilt = false;
0576 
0577   /**
0578    * Component used to select the options for corpus populating
0579    */
0580   protected CorpusFillerComponent corpusFiller;
0581 
0582   protected SingleConcatenatedFileInputDialog scfInputDialog;
0583 
0584   StatusListener sListenerProxy;
0585 
0586   private transient Vector<ProgressListener> progressListeners;
0587 
0588   private transient Vector<StatusListener> statusListeners;
0589 
0590   class CloseAction extends AbstractAction {
0591     public CloseAction() {
0592       super("Close");
0593       putValue(SHORT_DESCRIPTION, "Close this resource");
0594       putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control F4"));
0595     }
0596 
0597     public void actionPerformed(ActionEvent e) {
0598       if(target instanceof Controller) {
0599         // empty the controller of all its processing resources
0600         ((Controller)target).setPRs(Collections.emptyList());
0601         if(target instanceof ConditionalController) {
0602           ((ConditionalController)target).setRunningStrategies(Collections
0603                   .emptyList());
0604         }
0605       }
0606       if(target instanceof Resource) {
0607         Factory.deleteResource((Resource)target);
0608       }
0609       else if(target instanceof DataStore) {
0610         try {
0611           ((DataStore)target).close();
0612         }
0613         catch(PersistenceException pe) {
0614           JOptionPane.showMessageDialog(largeView != null
0615                   ? largeView
0616                   : smallView, "Error!\n" + pe.toString()"GATE",
0617                   JOptionPane.ERROR_MESSAGE);
0618         }
0619       }
0620       statusListeners.clear();
0621       progressListeners.clear();
0622     }
0623   }
0624 
0625   class CloseRecursivelyAction extends AbstractAction {
0626     public CloseRecursivelyAction() {
0627       super("Close Recursively");
0628       putValue(SHORT_DESCRIPTION,
0629               "Close this application and recursively all contained resources");
0630       putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("shift F4"));
0631     }
0632 
0633     public void actionPerformed(ActionEvent e) {
0634       Factory.deleteResource((Resource)target);
0635       statusListeners.clear();
0636       progressListeners.clear();
0637     }
0638   }
0639 
0640   /**
0641    * Used to save a document as XML
0642    */
0643   class SaveAsXmlAction extends AbstractAction {
0644     private static final long serialVersionUID = 1L;
0645 
0646     public SaveAsXmlAction() {
0647       super("Save as XML...");
0648       putValue(SHORT_DESCRIPTION, "Saves this resource in GATE XML format");
0649       putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control S"));
0650     }// SaveAsXmlAction()
0651 
0652     public void actionPerformed(ActionEvent e) {
0653       Runnable runableAction = new Runnable() {
0654         public void run() {
0655           XJFileChooser fileChooser = MainFrame.getFileChooser();
0656           ExtensionFileFilter filter = new ExtensionFileFilter("XML files",
0657                   "xml""gml");
0658           fileChooser.addChoosableFileFilter(filter);
0659           fileChooser.setMultiSelectionEnabled(false);
0660           fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
0661           fileChooser.setDialogTitle("Select document to save ...");
0662 
0663           gate.Document doc = (gate.Document)target;
0664           if(doc.getSourceUrl() != null) {
0665             String fileName = "";
0666             try {
0667               fileName = doc.getSourceUrl().toURI().getPath().trim();
0668             }
0669             catch(URISyntaxException e) {
0670               fileName = doc.getSourceUrl().getPath().trim();
0671             }
0672             if(fileName.equals(""|| fileName.equals("/")) {
0673               if(doc.getNamedAnnotationSets().containsKey("Original markups")
0674                       && !doc.getAnnotations("Original markups").get("title")
0675                               .isEmpty()) {
0676                 // use the title annotation if any
0677                 try {
0678                   fileName = doc.getContent().getContent(
0679                           doc.getAnnotations("Original markups").get("title")
0680                                   .firstNode().getOffset(),
0681                           doc.getAnnotations("Original markups").get("title")
0682                                   .lastNode().getOffset()).toString();
0683                 }
0684                 catch(InvalidOffsetException e) {
0685                   e.printStackTrace();
0686                 }
0687               }
0688               else {
0689                 fileName = doc.getSourceUrl().toString();
0690               }
0691               // cleans the file name
0692               fileName = fileName.replaceAll("/""_");
0693             }
0694             else {
0695               // replaces the extension with .xml
0696               fileName = fileName.replaceAll("\\.[a-zA-Z]{1,4}$"".xml");
0697             }
0698             // cleans the file name
0699             fileName = fileName.replaceAll("[^/a-zA-Z0-9._-]""_");
0700             fileName = fileName.replaceAll("__+""_");
0701             // adds a .xml extension if not present
0702             if(!fileName.endsWith(".xml")) {
0703               fileName += ".xml";
0704             }
0705             File file = new File(fileName);
0706             fileChooser.ensureFileIsVisible(file);
0707             fileChooser.setSelectedFile(file);
0708           }
0709 
0710           int res = (getLargeView() != null? fileChooser
0711                   .showSaveDialog(getLargeView()) (getSmallView() != null)
0712                   ? fileChooser.showSaveDialog(getSmallView())
0713                   : fileChooser.showSaveDialog(null);
0714           if(res == JFileChooser.APPROVE_OPTION) {
0715             File selectedFile = fileChooser.getSelectedFile();
0716             if(selectedFile == nullreturn;
0717             long start = System.currentTimeMillis();
0718             NameBearerHandle.this.statusChanged("Saving as XML to "
0719                     + selectedFile.toString() "...");
0720             try {
0721               MainFrame.lockGUI("Saving...");
0722               // Prepare to write into the xmlFile using the original
0723               // encoding
0724               // //////////////////////////////
0725               // String encoding =
0726               // ((gate.TextualDocument)target).getEncoding();
0727 
0728               // OutputStreamWriter writer = new OutputStreamWriter(
0729               // new FileOutputStream(selectedFile),
0730               // encoding);
0731 
0732               // Write (test the toXml() method)
0733               // This Action is added only when a gate.Document is
0734               // created.
0735               // So, is for sure that the resource is a gate.Document
0736               // writer.write(((gate.Document)target).toXml());
0737               // writer.flush();
0738               // writer.close();
0739 
0740               // write directly to the file using StAX
0741               DocumentStaxUtils.writeDocument((gate.Document)target,
0742                       selectedFile);
0743               ((gate.Document)target)
0744                       .setSourceUrl(selectedFile.toURI().toURL());
0745             }
0746             catch(Exception ex) {
0747               ex.printStackTrace(Out.getPrintWriter());
0748             }
0749             finally {
0750               MainFrame.unlockGUI();
0751             }
0752             long time = System.currentTimeMillis() - start;
0753             NameBearerHandle.this.statusChanged("Finished saving as xml into "
0754                     " the file: " + selectedFile.toString() " in "
0755                     ((double)time1000 " s");
0756           }// End if
0757         }// End run()
0758       };// End Runnable
0759       Thread thread = new Thread(runableAction, "");
0760       thread.setPriority(Thread.MIN_PRIORITY);
0761       thread.start();
0762     }// actionPerformed()
0763   }// SaveAsXmlAction
0764 
0765   /**
0766    * Saves a corpus as a set of xml files in a directory.
0767    */
0768   class SaveCorpusAsXmlAction extends AbstractAction {
0769     private static final long serialVersionUID = 1L;
0770 
0771     private boolean preserveFormat;
0772 
0773     public SaveCorpusAsXmlAction(boolean preserveFormat) {
0774       super("Save as XML...");
0775       putValue(SHORT_DESCRIPTION, "Saves each document in GATE XML format");
0776       this.preserveFormat = preserveFormat;
0777 
0778       if(preserveFormat) {
0779         putValue(NAME, "Save Preserving Format...");
0780         putValue(SHORT_DESCRIPTION, "Saves each document preserving its format");
0781       // if
0782     }// SaveAsXmlAction()
0783 
0784     public void actionPerformed(ActionEvent e) {
0785       Runnable runnable = new Runnable() {
0786         public void run() {
0787           if(preserveFormatSystem.out.println("Preserve option set!");
0788           try {
0789             // we need a directory
0790             XJFileChooser fileChooser = MainFrame.getFileChooser();
0791             fileChooser
0792                     .setDialogTitle("Select the directory that will contain the corpus");
0793             fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
0794 
0795             if(fileChooser.showDialog(getLargeView() != null
0796                     ? getLargeView()
0797                     : getSmallView()"Select"== JFileChooser.APPROVE_OPTION) {
0798 
0799               File dir = fileChooser.getSelectedFile();
0800               // create the top directory if needed
0801               if(!dir.exists()) {
0802                 if(!dir.mkdirs()) {
0803                   JOptionPane.showMessageDialog(largeView != null
0804                           ? largeView
0805                           : smallView, "Could not create top directory!",
0806                           "GATE", JOptionPane.ERROR_MESSAGE);
0807                   return;
0808                 }
0809               }
0810 
0811               MainFrame.lockGUI("Saving...");
0812 
0813               // iterate through all the docs and save each of them as
0814               // xml
0815               Corpus corpus = (Corpus)target;
0816               Iterator docIter = corpus.iterator();
0817               boolean overwriteAll = false;
0818               int docCnt = corpus.size();
0819               int currentDocIndex = 0;
0820               while(docIter.hasNext()) {
0821                 boolean docWasLoaded = corpus.isDocumentLoaded(currentDocIndex);
0822                 Document currentDoc = (Document)docIter.next();
0823                 URL sourceURL = currentDoc.getSourceUrl();
0824                 String fileName = null;
0825                 if(sourceURL != null) {
0826                   fileName = sourceURL.getFile();
0827                   fileName = Files.getLastPathComponent(fileName);
0828                 }
0829                 if(fileName == null || fileName.length() == 0) {
0830                   fileName = currentDoc.getName();
0831                 }
0832                 // makes sure that the filename does not contain any
0833                 // forbidden character
0834                 fileName = fileName.replaceAll("[\\/:\\*\\?\"<>|]""_");
0835 
0836                 if(!fileName.toLowerCase().endsWith(".xml"))
0837                   fileName += ".xml";
0838                 File docFile = null;
0839                 boolean nameOK = false;
0840                 do {
0841                   docFile = new File(dir, fileName);
0842                   if(docFile.exists() && !overwriteAll) {
0843                     // ask the user if we can ovewrite the file
0844                     Object[] options = new Object[] {"Yes""All""No",
0845                         "Cancel"};
0846                     MainFrame.unlockGUI();
0847                     int answer = JOptionPane.showOptionDialog(largeView != null
0848                             ? largeView
0849                             : smallView, "File " + docFile.getName()
0850                             " already exists!\n" "Overwrite?""GATE",
0851                             JOptionPane.DEFAULT_OPTION,
0852                             JOptionPane.WARNING_MESSAGE, null, options,
0853                             options[2]);
0854                     MainFrame.lockGUI("Saving...");
0855                     switch(answer) {
0856                       case 0{
0857                         nameOK = true;
0858                         break;
0859                       }
0860                       case 1{
0861                         nameOK = true;
0862                         overwriteAll = true;
0863                         break;
0864                       }
0865                       case 2{
0866                         // user said NO, allow them to provide an
0867                         // alternative name;
0868                         MainFrame.unlockGUI();
0869                         fileName = (String)JOptionPane.showInputDialog(
0870                                 largeView != null ? largeView : smallView,
0871                                 "Please provide an alternative file name",
0872                                 "GATE", JOptionPane.QUESTION_MESSAGE, null,
0873                                 null, fileName);
0874                         if(fileName == null) {
0875                           fireProcessFinished();
0876                           return;
0877                         }
0878                         MainFrame.lockGUI("Saving");
0879                         break;
0880                       }
0881                       case 3{
0882                         // user gave up; return
0883                         fireProcessFinished();
0884                         return;
0885                       }
0886                     }
0887 
0888                   }
0889                   else {
0890                     nameOK = true;
0891                   }
0892                 while(!nameOK);
0893                 // save the file
0894                 try {
0895                   String content = "";
0896                   // check for preserve format flag
0897                   if(preserveFormat) {
0898                     Set annotationsToDump = null;
0899                     // Find the shown document editor.
0900                     // If none, just dump the original markup
0901                     // annotations,
0902                     // i.e., leave the annotationsToDump null
0903                     if(largeView instanceof JTabbedPane) {
0904                       Component shownComponent = ((JTabbedPane)largeView)
0905                               .getSelectedComponent();
0906                       if(shownComponent instanceof DocumentEditor) {
0907                         // so we only get annotations for dumping
0908                         // if they are shown in the table of the
0909                         // document editor,
0910                         // which is currently in front of the user
0911                         annotationsToDump = ((DocumentEditor)shownComponent)
0912                                 .getDisplayedAnnotations();
0913                       }// if we have a document editor
0914                     }// if tabbed pane
0915 
0916                     // determine if the features need to be saved first
0917                     Boolean featuresSaved = Gate.getUserConfig().getBoolean(
0918                             GateConstants.SAVE_FEATURES_WHEN_PRESERVING_FORMAT);
0919                     boolean saveFeatures = true;
0920                     if(featuresSaved != null)
0921                       saveFeatures = featuresSaved.booleanValue();
0922 
0923                     // Write with the toXml() method
0924                     content = currentDoc.toXml(annotationsToDump, saveFeatures);
0925 
0926                     // Prepare to write into the xmlFile using the
0927                     // original encoding
0928                     String encoding = ((gate.TextualDocument)currentDoc)
0929                             .getEncoding();
0930 
0931                     OutputStreamWriter writer = new OutputStreamWriter(
0932                             new FileOutputStream(docFile), encoding);
0933 
0934                     writer.write(content);
0935                     writer.flush();
0936                     writer.close();
0937                   }
0938                   else {
0939                     // for GATE XML format, use the direct StAX writer
0940                     DocumentStaxUtils.writeDocument(currentDoc, docFile);
0941                   // if
0942                 }
0943                 catch(Exception ioe) {
0944                   MainFrame.unlockGUI();
0945                   JOptionPane.showMessageDialog(largeView != null
0946                           ? largeView
0947                           : smallView, "Could not create write file:"
0948                           + ioe.toString()"GATE", JOptionPane.ERROR_MESSAGE);
0949                   ioe.printStackTrace(Err.getPrintWriter());
0950                   return;
0951                 }
0952 
0953                 fireStatusChanged(currentDoc.getName() " saved");
0954                 // close the doc if it wasn't already loaded
0955                 if(!docWasLoaded) {
0956                   corpus.unloadDocument(currentDoc);
0957                   Factory.deleteResource(currentDoc);
0958                 }
0959 
0960                 fireProgressChanged(100 * currentDocIndex++ / docCnt);
0961               }// while(docIter.hasNext())
0962               fireStatusChanged("Corpus saved");
0963               fireProcessFinished();
0964             }// select directory
0965           }
0966           finally {
0967             MainFrame.unlockGUI();
0968           }
0969         }// public void run(){
0970       };// Runnable runnable = new Runnable()
0971       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
0972               runnable, "Corpus XML dumper");
0973       thread.setPriority(Thread.MIN_PRIORITY);
0974       thread.start();
0975 
0976     }// public void actionPerformed(ActionEvent e)
0977   }// class SaveCorpusAsXmlAction extends AbstractAction
0978 
0979   /**
0980    * Saves a corpus as a set of xml files in a directory.
0981    */
0982   class ReloadClassAction extends AbstractAction {
0983     private static final long serialVersionUID = 1L;
0984 
0985     public ReloadClassAction() {
0986       super("Reload Resource Class");
0987       putValue(SHORT_DESCRIPTION, "Reloads the java class for this resource");
0988     }
0989 
0990     public void actionPerformed(ActionEvent e) {
0991       int answer = JOptionPane.showOptionDialog(largeView != null
0992               ? largeView
0993               : smallView, "This is an advanced option!\n"
0994               "You should not use this unless your name is Hamish.\n"
0995               "Are you sure you want to do this?""GATE",
0996               JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null,
0997               null, null);
0998       if(answer == JOptionPane.OK_OPTION) {
0999         try {
1000           String className = target.getClass().getName();
1001           Gate.getClassLoader().reloadClass(className);
1002           fireStatusChanged("Class " + className + " reloaded!");
1003         }
1004         catch(Exception ex) {
1005           JOptionPane.showMessageDialog(largeView != null
1006                   ? largeView
1007                   : smallView, "Look what you've done: \n" + ex.toString()
1008                   "\nI told you not to do it...""GATE",
1009                   JOptionPane.ERROR_MESSAGE);
1010           ex.printStackTrace(Err.getPrintWriter());
1011         }
1012       }
1013     }
1014   }
1015 
1016   class SaveAction extends AbstractAction {
1017     private static final long serialVersionUID = 1L;
1018 
1019     public SaveAction() {
1020       super("Save to its Datastore");
1021       putValue(SHORT_DESCRIPTION, "Save back to its datastore");
1022     }
1023 
1024     public void actionPerformed(ActionEvent e) {
1025       Runnable runnable = new Runnable() {
1026         public void run() {
1027           DataStore ds = ((LanguageResource)target).getDataStore();
1028           if(ds != null) {
1029             try {
1030               MainFrame.lockGUI("Saving "
1031                       ((LanguageResource)target).getName());
1032               StatusListener sListener = (StatusListener)gate.Gate
1033                       .getListeners().get("gate.event.StatusListener");
1034               if(sListener != null)
1035                 sListener.statusChanged("Saving: "
1036                         ((LanguageResource)target).getName());
1037               double timeBefore = System.currentTimeMillis();
1038               ((LanguageResource)target).getDataStore().sync(
1039                       (LanguageResource)target);
1040               double timeAfter = System.currentTimeMillis();
1041               if(sListener != null)
1042                 sListener.statusChanged(((LanguageResource)target).getName()
1043                         " saved in "
1044                         + NumberFormat.getInstance().format(
1045                                 (timeAfter - timeBefore1000" seconds");
1046             }
1047             catch(PersistenceException pe) {
1048               MainFrame.unlockGUI();
1049               JOptionPane.showMessageDialog(getLargeView()"Save failed!\n "
1050                       + pe.toString()"GATE", JOptionPane.ERROR_MESSAGE);
1051             }
1052             catch(SecurityException se) {
1053               MainFrame.unlockGUI();
1054               JOptionPane.showMessageDialog(getLargeView()"Save failed!\n "
1055                       + se.toString()"GATE", JOptionPane.ERROR_MESSAGE);
1056             }
1057             finally {
1058               MainFrame.unlockGUI();
1059             }
1060           }
1061           else {
1062             JOptionPane
1063                     .showMessageDialog(
1064                             getLargeView(),
1065                             "This resource has not been loaded from a datastore.\n"
1066                                     "Please use the \"Save to Datastore...\" option.\n",
1067                             "GATE", JOptionPane.ERROR_MESSAGE);
1068 
1069           }
1070         }
1071       };
1072       new Thread(runnable).start();
1073     }// public void actionPerformed(ActionEvent e)
1074   }// class SaveAction
1075 
1076   class DumpToFileAction extends AbstractAction {
1077     private static final long serialVersionUID = 1L;
1078 
1079     public DumpToFileAction() {
1080       super("Save Application State");
1081       putValue(SHORT_DESCRIPTION,
1082               "Saves the data needed to recreate this application");
1083     }
1084 
1085     public void actionPerformed(ActionEvent ae) {
1086       final XJFileChooser fileChooser = MainFrame.getFileChooser();
1087       ExtensionFileFilter filter = new ExtensionFileFilter(
1088               "GATE Application files""gapp");
1089       fileChooser.addChoosableFileFilter(filter);
1090       fileChooser
1091               .setDialogTitle("Select a file where to save the application "
1092                       ((target instanceof CorpusController && ((CorpusController)target)
1093                               .getCorpus() != null"WITH" "WITHOUT")
1094                       " corpus.");
1095       fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
1096       fileChooser.setResource("application." + target.getName());
1097 
1098       if(fileChooser.showSaveDialog(largeView== JFileChooser.APPROVE_OPTION) {
1099         final File file = fileChooser.getSelectedFile();
1100         Runnable runnable = new Runnable() {
1101           public void run() {
1102             try {
1103               Map<String, String> locations = fileChooser.getLocations();
1104               // When saving an application state, use paths relative to
1105               // GATE HOME for resources inside GATE HOME and warn about
1106               // them.
1107               gate.util.persistence.PersistenceManager.saveObjectToFile(target,
1108                       file, true, true);
1109               // save also the location of the application as last
1110               // application
1111               locations.put("lastapplication", file.getCanonicalPath());
1112               // add this application to the list of recent applications
1113               String list = locations.get("applications");
1114               if(list == null) {
1115                 list = "";
1116               }
1117               list = list.replaceFirst("\\Q" + target.getName() "\\E(;|$)",
1118                       "");
1119               list = target.getName() ";" + list;
1120               locations.put("applications", list);
1121               fileChooser.setLocations(locations);
1122             }
1123             catch(Exception e) {
1124               JOptionPane.showMessageDialog(getLargeView()"Error!\n"
1125                       + e.toString()"GATE", JOptionPane.ERROR_MESSAGE);
1126               e.printStackTrace(Err.getPrintWriter());
1127             }
1128           }
1129         };
1130         Thread thread = new Thread(runnable);
1131         thread.setPriority(Thread.MIN_PRIORITY);
1132         thread.start();
1133       }
1134     }
1135 
1136   }
1137 
1138   class ExportApplicationAction extends AbstractAction {
1139     private Logger log = Logger.getLogger("gate.gui.ExportApplicationAction");
1140 
1141     private static final long serialVersionUID = 1L;
1142 
1143     public ExportApplicationAction() {
1144       super("Export for GATECloud.net");
1145       putValue(SHORT_DESCRIPTION,
1146               "Saves the resources of this application in a ZIP file");
1147     }
1148 
1149     /**
1150      * Build listener to receive log messages from Ant tasks and forward
1151      * them to the GATE status listener (i.e. the status bar). This
1152      * class implements Executable not because it is itself executed,
1153      * but in order to support interruption. If the user presses the
1154      * stop button in the GUI lock window this object will be
1155      * interrupted, and will throw an exception at the next call to
1156      * messageLogged, which has the effect of interrupting the currently
1157      * executing Ant task.
1158      */
1159     class ExporterBuildListener implements BuildListener, Executable {
1160       private boolean interrupted = false;
1161 
1162       public boolean isInterrupted() {
1163         return interrupted;
1164       }
1165 
1166       public void interrupt() {
1167         interrupted = true;
1168       }
1169 
1170       /**
1171        * Set status message appropriately when task completes or fails.
1172        */
1173       public void taskFinished(BuildEvent buildEvent) {
1174         if(buildEvent.getException() != null) {
1175           statusChanged("Error exporting application");
1176         }
1177         else {
1178           statusChanged("Export complete");
1179         }
1180       }
1181 
1182       /**
1183        * This is called for every log message (of any priority). If the
1184        * current process has been interrupted (the user pressed the stop
1185        * button) then we throw an exception to interrupt the currently
1186        * executing Ant task. Other than that, we simply pass INFO and
1187        * higher messages to the GATE status listener.
1188        */
1189       public void messageLogged(BuildEvent buildEvent) {
1190         // check for interruption
1191         if(interrupted) {
1192           interrupted = false;
1193           throw new BuildException("Export interrupted");
1194         }
1195         if(buildEvent.getPriority() <= Project.MSG_INFO) {
1196           statusChanged(buildEvent.getMessage());
1197         }
1198         // log the message to log4j for debugging purposes
1199         log.debug(buildEvent.getPriority() ": " + buildEvent.getMessage());
1200       }
1201 
1202       // not interested in these events
1203       public void buildStarted(BuildEvent buildEvent) {
1204       }
1205 
1206       public void buildFinished(BuildEvent buildEvent) {
1207       }
1208 
1209       public void targetStarted(BuildEvent buildEvent) {
1210       }
1211 
1212       public void targetFinished(BuildEvent buildEvent) {
1213       }
1214 
1215       public void taskStarted(BuildEvent buildEvent) {
1216       }
1217 
1218       public void execute() {
1219         // do nothing, only here to match the interface
1220       }
1221     }
1222 
1223     public void actionPerformed(ActionEvent ae) {
1224       XJFileChooser fileChooser = MainFrame.getFileChooser();
1225       ExtensionFileFilter filter = new ExtensionFileFilter("ZIP file""zip");
1226       fileChooser.addChoosableFileFilter(filter);
1227       fileChooser
1228               .setDialogTitle("Select a file where to save the application "
1229                       ((target instanceof CorpusController && ((CorpusController)target)
1230                               .getCorpus() != null"WITH" "WITHOUT")
1231                       " corpus.");
1232       fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
1233       fileChooser.setResource("application.zip." + target.getName());
1234 
1235       if(fileChooser.showSaveDialog(largeView== JFileChooser.APPROVE_OPTION) {
1236         final File targetZipFile = fileChooser.getSelectedFile();
1237         Runnable runnable = new Runnable() {
1238           public void run() {
1239             try {
1240               // create and configure Ant Project
1241               Project project = new Project();
1242               ExporterBuildListener buildListener = new ExporterBuildListener();
1243               Gate.setExecutable(buildListener);
1244               project.addBuildListener(buildListener);
1245               project.init();
1246               MainFrame.lockGUI("Exporting application...");
1247 
1248               // create a temporary directory, and save the
1249               // application
1250               // in the normal way to that directory
1251               File temporaryDirectory = File.createTempFile("gapp-packager",
1252                       ""null);
1253               if(!temporaryDirectory.delete() || !temporaryDirectory.mkdir()) {
1254                 throw new IOException(
1255                         "Unable to create temporary directory.\n"
1256                                 + temporaryDirectory.getCanonicalPath());
1257               }
1258               // canonicalise (e.g. on Mac OS X java.io.tmpdir is
1259               // /var/folders/something, but /var is a symlink to
1260               // /private/var,
1261               // and this can confuse the relpaths which are based on
1262               // canonical
1263               // path strings)
1264               temporaryDirectory = temporaryDirectory.getCanonicalFile();
1265               File originalGapp = new File(temporaryDirectory,
1266                       "original.xgapp");
1267               File targetGapp = new File(temporaryDirectory,
1268                       "application.xgapp");
1269 
1270               // save the application in a gapp file
1271               // When exporting to cloud, the gapp file should not
1272               // contain
1273               // any paths relative to GATE HOME, but we still warn
1274               // about
1275               // resources under GATE HOME
1276               gate.util.persistence.PersistenceManager.saveObjectToFile(
1277                       target, originalGapp, false, true);
1278 
1279               // create instance of packager task and configure it
1280               PackageGappTask task = new PackageGappTask();
1281               task.setProject(project);
1282               task.setSrc(originalGapp);
1283               task.setDestFile(targetGapp);
1284               // sensible default settings
1285               task.setCopyPlugins(true);
1286               task.setCopyResourceDirs(true);
1287               task.setOnUnresolved(PackageGappTask.UnresolvedAction.recover);
1288               task.init();
1289 
1290               // run the task.
1291               task.perform();
1292 
1293               // create zip file using standard Ant zip task
1294               Zip zipTask = new Zip();
1295               zipTask.setProject(project);
1296               zipTask.setDestFile(targetZipFile);
1297               FileSet fs = new FileSet();
1298               fs.setProject(project);
1299               zipTask.addFileset(fs);
1300               fs.setDir(temporaryDirectory);
1301               // exclude the unpackaged gapp file from the zip
1302               fs.setExcludes("original.xgapp");
1303               zipTask.perform();
1304 
1305               // delete temporary files
1306               Delete deleteTask = new Delete();
1307               deleteTask.setProject(project);
1308               deleteTask.setDir(temporaryDirectory);
1309               deleteTask.perform();
1310             }
1311             catch(Exception e) {
1312               MainFrame.unlockGUI();
1313               JOptionPane.showMessageDialog(getLargeView()"Error!\n"
1314                       + e.toString()"GATE", JOptionPane.ERROR_MESSAGE);
1315               e.printStackTrace(Err.getPrintWriter());
1316             }
1317             finally {
1318               MainFrame.unlockGUI();
1319               Gate.setExecutable(null);
1320             }
1321           }
1322         };
1323         Thread thread = new Thread(runnable);
1324         thread.setPriority(Thread.MIN_PRIORITY);
1325         thread.start();
1326       }
1327     }
1328 
1329   }
1330 
1331   class SaveToAction extends AbstractAction {
1332     private static final long serialVersionUID = 1L;
1333 
1334     public SaveToAction() {
1335       super("Save to Datastore...");
1336       putValue(SHORT_DESCRIPTION, "Save this resource to a datastore");
1337     }
1338 
1339     public void actionPerformed(ActionEvent e) {
1340       Runnable runnable = new Runnable() {
1341         public void run() {
1342           try {
1343             DataStoreRegister dsReg = Gate.getDataStoreRegister();
1344             Map<String, DataStore> dsByName = new HashMap<String, DataStore>();
1345             Iterator dsIter = dsReg.iterator();
1346             while(dsIter.hasNext()) {
1347               DataStore oneDS = (DataStore)dsIter.next();
1348               String name;
1349               if((name = (String)oneDS.getName()) != null) {
1350               }
1351               else {
1352                 name = oneDS.getStorageUrl();
1353                 try {
1354                   URL tempURL = new URL(name);
1355                   name = tempURL.getFile();
1356                 }
1357                 catch(java.net.MalformedURLException ex) {
1358                   throw new GateRuntimeException();
1359                 }
1360               }
1361               dsByName.put(name, oneDS);
1362             }
1363             List<String> dsNames = new ArrayList<String>(dsByName.keySet());
1364             if(dsNames.isEmpty()) {
1365               JOptionPane.showMessageDialog(getLargeView(),
1366                       "There are no open datastores!\n "
1367                               "Please open a datastore first!""GATE",
1368                       JOptionPane.ERROR_MESSAGE);
1369 
1370             }
1371             else {
1372               Object answer = JOptionPane.showInputDialog(getLargeView(),
1373                       "Select the datastore""GATE",
1374                       JOptionPane.QUESTION_MESSAGE, null, dsNames.toArray(),
1375                       dsNames.get(0));
1376               if(answer == nullreturn;
1377               DataStore ds = (DataStore)dsByName.get(answer);
1378               if(ds == null) {
1379                 Err.prln("The datastore does not exists. Saving procedure"
1380                         " has FAILED! This should never happen again!");
1381                 return;
1382               }// End if
1383               DataStore ownDS = ((LanguageResource)target).getDataStore();
1384               if(ds == ownDS) {
1385                 MainFrame.lockGUI("Saving "
1386                         ((LanguageResource)target).getName());
1387 
1388                 StatusListener sListener = (StatusListener)gate.Gate
1389                         .getListeners().get("gate.event.StatusListener");
1390                 if(sListener != null)
1391                   sListener.statusChanged("Saving: "
1392                           ((LanguageResource)target).getName());
1393                 double timeBefore = System.currentTimeMillis();
1394                 ds.sync((LanguageResource)target);
1395                 double timeAfter = System.currentTimeMillis();
1396                 if(sListener != null)
1397                   sListener
1398                           .statusChanged(((LanguageResource)target).getName()
1399                                   " saved in "
1400                                   + NumberFormat.getInstance().format(
1401                                           (timeAfter - timeBefore1000)
1402                                   " seconds");
1403               }
1404               else {
1405                 FeatureMap securityData = (FeatureMap)DataStoreRegister
1406                         .getSecurityData(ds);
1407                 SecurityInfo si = null;
1408                 // check whether the datastore supports security data
1409                 // serial ones do not for example
1410                 if(securityData != null) {
1411                   // first get the type of access from the user
1412                   if(!AccessRightsDialog.showDialog(window)) return;
1413                   int accessType = AccessRightsDialog.getSelectedMode();
1414                   if(accessType < 0return;
1415                   si = new SecurityInfo(accessType, (User)securityData
1416                           .get("user")(Group)securityData.get("group"));
1417                 }// if security info
1418                 StatusListener sListener = (StatusListener)gate.Gate
1419                         .getListeners().get("gate.event.StatusListener");
1420                 MainFrame.lockGUI("Saving "
1421                         ((LanguageResource)target).getName());
1422 
1423                 if(sListener != null)
1424                   sListener.statusChanged("Saving: "
1425                           ((LanguageResource)target).getName());
1426                 double timeBefore = System.currentTimeMillis();
1427                 LanguageResource lr = ds.adopt((LanguageResource)target, si);
1428                 ds.sync(lr);
1429                 if(ds instanceof LuceneDataStoreImpl
1430                         && lr instanceof IndexedCorpus) {
1431                   Object persistanceID = lr.getLRPersistenceId();
1432                   String lrType = lr.getClass().getName();
1433                   String lrName = lr.getName();
1434                   Factory.deleteResource(lr);
1435                   FeatureMap params = Factory.newFeatureMap();
1436                   params.put(DataStore.DATASTORE_FEATURE_NAME, ds);
1437                   params.put(DataStore.LR_ID_FEATURE_NAME, persistanceID);
1438                   FeatureMap features = Factory.newFeatureMap();
1439                   try {
1440                     lr = (LanguageResource)Factory.createResource(lrType,
1441                             params, features, lrName);
1442                   }
1443                   catch(ResourceInstantiationException rie) {
1444                     throw new GateRuntimeException("Could not load the corpus",
1445                             rie);
1446                   }
1447                 }
1448 
1449                 double timeAfter = System.currentTimeMillis();
1450                 if(sListener != null)
1451                   sListener
1452                           .statusChanged(((LanguageResource)target).getName()
1453                                   " saved in "
1454                                   + NumberFormat.getInstance().format(
1455                                           (timeAfter - timeBefore1000)
1456                                   " seconds");
1457 
1458                 // check whether the new LR is different from the
1459                 // transient one and
1460                 // if so, unload the transient LR, so the user realises
1461                 // it is no longer valid. Don't do this in the adopt()
1462                 // code itself
1463                 // because the batch code might wish to keep the
1464                 // transient
1465                 // resource for some purpose.
1466                 if(lr != target) {
1467                   Factory.deleteResource((LanguageResource)target);
1468                 }
1469               }
1470             }
1471           }
1472           catch(PersistenceException pe) {
1473             MainFrame.unlockGUI();
1474             JOptionPane.showMessageDialog(getLargeView()"Save failed!\n "
1475                     + pe.toString()"GATE", JOptionPane.ERROR_MESSAGE);
1476           }
1477           catch(gate.security.SecurityException se) {
1478             MainFrame.unlockGUI();
1479             JOptionPane.showMessageDialog(getLargeView()"Save failed!\n "
1480                     + se.toString()"GATE", JOptionPane.ERROR_MESSAGE);
1481           }
1482           finally {
1483             MainFrame.unlockGUI();
1484           }
1485 
1486         }
1487       };
1488       new Thread(runnable).start();
1489     }
1490   }// class SaveToAction extends AbstractAction
1491 
1492   class ReloadAction extends AbstractAction {
1493     private static final long serialVersionUID = 1L;
1494 
1495     ReloadAction() {
1496       super("Reinitialise");
1497       putValue(SHORT_DESCRIPTION, "Reloads this resource");
1498     }
1499 
1500     public void actionPerformed(ActionEvent e) {
1501       Runnable runnable = new Runnable() {
1502         public void run() {
1503           if(!(target instanceof ProcessingResource)) return;
1504           if(target instanceof Controllerreturn;
1505           try {
1506             long startTime = System.currentTimeMillis();
1507             fireStatusChanged("Reinitialising " + target.getName());
1508             Map<String, EventListener> listeners = new HashMap<String, EventListener>();
1509             StatusListener sListener = new StatusListener() {
1510               public void statusChanged(String text) {
1511                 fireStatusChanged(text);
1512               }
1513             };
1514             listeners.put("gate.event.StatusListener", sListener);
1515 
1516             ProgressListener pListener = new ProgressListener() {
1517               public void progressChanged(int value) {
1518                 fireProgressChanged(value);
1519               }
1520 
1521               public void processFinished() {
1522                 fireProcessFinished();
1523               }
1524             };
1525             listeners.put("gate.event.ProgressListener", pListener);
1526 
1527             ProcessingResource res = (ProcessingResource)target;
1528             try {
1529               AbstractResource.setResourceListeners(res, listeners);
1530             }
1531             catch(Exception e) {
1532               e.printStackTrace(Err.getPrintWriter());
1533             }
1534             // show the progress indicator
1535             fireProgressChanged(0);
1536             // the actual reinitialisation
1537             res.reInit();
1538             try {
1539               AbstractResource.removeResourceListeners(res, listeners);
1540             }
1541             catch(Exception e) {
1542               e.printStackTrace(Err.getPrintWriter());
1543             }
1544             long endTime = System.currentTimeMillis();
1545             fireStatusChanged(target.getName()
1546                     " reinitialised in "
1547                     + NumberFormat.getInstance().format(
1548                             (double)(endTime - startTime1000" seconds");
1549             fireProcessFinished();
1550           }
1551           catch(ResourceInstantiationException rie) {
1552             fireStatusChanged("reinitialisation failed");
1553             rie.printStackTrace(Err.getPrintWriter());
1554             JOptionPane.showMessageDialog(getLargeView()"Reload failed!\n "
1555                     "See \"Messages\" tab for details!""GATE",
1556                     JOptionPane.ERROR_MESSAGE);
1557             fireProcessFinished();
1558           }
1559         }// public void run()
1560       };
1561       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1562               runnable, "DefaultResourceHandle1");
1563       thread.setPriority(Thread.MIN_PRIORITY);
1564       thread.start();
1565     }// public void actionPerformed(ActionEvent e)
1566 
1567   }// class ReloadAction
1568 
1569   class PopulateCorpusAction extends AbstractAction {
1570     private static final long serialVersionUID = 1L;
1571 
1572     PopulateCorpusAction() {
1573       super("Populate");
1574       putValue(SHORT_DESCRIPTION,
1575               "Fills this corpus with documents from a directory");
1576     }
1577 
1578     public void actionPerformed(ActionEvent e) {
1579       corpusFiller.setExtensions(new ArrayList());
1580       corpusFiller.setEncoding("");
1581       final boolean answer = OkCancelDialog.showDialog(window, corpusFiller,
1582               "Select a directory and allowed extensions");
1583       Runnable runnable = new Runnable() {
1584         public void run() {
1585           if(answer) {
1586             long startTime = System.currentTimeMillis();
1587             URL url;
1588             try {
1589               url = new URL(corpusFiller.getUrlString());
1590               java.util.List extensions = corpusFiller.getExtensions();
1591               ExtensionFileFilter filter;
1592               if(extensions == null || extensions.isEmpty()) {
1593                 filter = null;
1594               }
1595               else {
1596                 filter = new ExtensionFileFilter();
1597                 Iterator extIter = corpusFiller.getExtensions().iterator();
1598                 while(extIter.hasNext()) {
1599                   filter.addExtension((String)extIter.next());
1600                 }
1601               }
1602               String encoding = corpusFiller.getEncoding();
1603               if(encoding != null && encoding.trim().length() == 0) {
1604                 encoding = null;
1605               }
1606               String mimeType = corpusFiller.getMimeType();
1607               if(mimeType != null && mimeType.trim().length() == 0) {
1608                 mimeType = null;
1609               }
1610               ((Corpus)target).populate(url, filter, encoding, mimeType,
1611                       corpusFiller.isRecurseDirectories());
1612               if(((Corpus)target).getDataStore() != null) {
1613                 ((LanguageResource)target).getDataStore().sync(
1614                         (LanguageResource)target);
1615               }
1616 
1617               long endTime = System.currentTimeMillis();
1618               fireStatusChanged("Corpus populated in "
1619                       + NumberFormat.getInstance().format(
1620                               (double)(endTime - startTime1000)
1621                       " seconds!");
1622 
1623             }
1624             catch(MalformedURLException mue) {
1625               JOptionPane.showMessageDialog(getLargeView()"Invalid URL!\n "
1626                       "See \"Messages\" tab for details!""GATE",
1627                       JOptionPane.ERROR_MESSAGE);
1628               mue.printStackTrace(Err.getPrintWriter());
1629             }
1630             catch(IOException ioe) {
1631               JOptionPane.showMessageDialog(getLargeView()"I/O error!\n "
1632                       "See \"Messages\" tab for details!""GATE",
1633                       JOptionPane.ERROR_MESSAGE);
1634               ioe.printStackTrace(Err.getPrintWriter());
1635             }
1636             catch(ResourceInstantiationException rie) {
1637               JOptionPane.showMessageDialog(getLargeView(),
1638                       "Could not create document!\n "
1639                               "See \"Messages\" tab for details!""GATE",
1640                       JOptionPane.ERROR_MESSAGE);
1641               rie.printStackTrace(Err.getPrintWriter());
1642             }
1643             catch(PersistenceException pe) {
1644               JOptionPane.showMessageDialog(getLargeView(),
1645                       "Corpus couldn't be synchronized!\n "
1646                               "See \"Messages\" tab for details!""GATE",
1647                       JOptionPane.ERROR_MESSAGE);
1648               pe.printStackTrace(Err.getPrintWriter());
1649             }
1650             catch(SecurityException pe) {
1651               JOptionPane.showMessageDialog(getLargeView(),
1652                       "Corpus couldn't be synchronized!\n "
1653                               "See \"Messages\" tab for details!""GATE",
1654                       JOptionPane.ERROR_MESSAGE);
1655               pe.printStackTrace(Err.getPrintWriter());
1656             }
1657           }
1658         }
1659       };
1660       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1661               runnable, "PopulateCorpusAction");
1662       thread.setPriority(Thread.MIN_PRIORITY);
1663       thread.start();
1664     }
1665   }
1666 
1667   class PopulateCorpusFromSingleConcatenatedFileAction extends AbstractAction {
1668     private static final long serialVersionUID = 2342321851865139492L;
1669 
1670     PopulateCorpusFromSingleConcatenatedFileAction() {
1671       super("Populate from Single Concatenated File");
1672       putValue(SHORT_DESCRIPTION,
1673               "Fills this corpus by extracting multiple documents from a single file");
1674     }
1675 
1676     public void actionPerformed(ActionEvent e) {
1677       scfInputDialog.setEncoding("");
1678       final boolean answer = OkCancelDialog.showDialog(window, scfInputDialog,
1679               "Select a trecweb file");
1680       Runnable runnable = new Runnable() {
1681         public void run() {
1682           if(answer) {
1683 
1684             String message = null;
1685             // lets first check the parameters
1686             if(scfInputDialog.getUrlString().trim().length() == 0) {
1687               message = "file URL cannot be empty";
1688             }
1689             else if(scfInputDialog.getDocumentRootElement().trim().length() == 0) {
1690               message = "document root element cannot be empty";
1691             }
1692 
1693             // if something wrong say it to the user
1694             if(message != null) {
1695               JOptionPane.showMessageDialog(getLargeView(), message, "GATE",
1696                       JOptionPane.ERROR_MESSAGE);
1697               return;
1698             }
1699 
1700             // all parameters fine, proceed 
1701             long startTime = System.currentTimeMillis();
1702             URL url = null;
1703             try {
1704               url = new URL(scfInputDialog.getUrlString());
1705               ((Corpus)target).populate(url, scfInputDialog
1706                       .getDocumentRootElement(), scfInputDialog.getEncoding(),
1707                       scfInputDialog.getNumOfDocumentsToFetch(), scfInputDialog
1708                               .getDocumentNamePrefix(), scfInputDialog
1709                               .getDocumentType());
1710               if(((Corpus)target).getDataStore() != null) {
1711                 ((LanguageResource)target).getDataStore().sync(
1712                         (LanguageResource)target);
1713               }
1714 
1715               long endTime = System.currentTimeMillis();
1716               fireStatusChanged("Corpus populated in "
1717                       + NumberFormat.getInstance().format(
1718                               (double)(endTime - startTime1000)
1719                       " seconds!");
1720 
1721             }
1722             catch(MalformedURLException mue) {
1723               JOptionPane.showMessageDialog(getLargeView()"Invalid URL!\n "
1724                       "See \"Messages\" tab for details!""GATE",
1725                       JOptionPane.ERROR_MESSAGE);
1726               mue.printStackTrace(Err.getPrintWriter());
1727             }
1728             catch(IOException ioe) {
1729               JOptionPane.showMessageDialog(getLargeView()"I/O error!\n "
1730                       "See \"Messages\" tab for details!""GATE",
1731                       JOptionPane.ERROR_MESSAGE);
1732               ioe.printStackTrace(Err.getPrintWriter());
1733             }
1734             catch(ResourceInstantiationException rie) {
1735               JOptionPane.showMessageDialog(getLargeView(),
1736                       "Could not create document!\n "
1737                               "See \"Messages\" tab for details!""GATE",
1738                       JOptionPane.ERROR_MESSAGE);
1739               rie.printStackTrace(Err.getPrintWriter());
1740             }
1741             catch(PersistenceException pe) {
1742               JOptionPane.showMessageDialog(getLargeView(),
1743                       "Corpus couldn't be synchronized!\n "
1744                               "See \"Messages\" tab for details!""GATE",
1745                       JOptionPane.ERROR_MESSAGE);
1746               pe.printStackTrace(Err.getPrintWriter());
1747             }
1748             catch(SecurityException pe) {
1749               JOptionPane.showMessageDialog(getLargeView(),
1750                       "Corpus couldn't be synchronized!\n "
1751                               "See \"Messages\" tab for details!""GATE",
1752                       JOptionPane.ERROR_MESSAGE);
1753               pe.printStackTrace(Err.getPrintWriter());
1754             }
1755           }
1756         }
1757       };
1758       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1759               runnable, "PopulateCorpusFromSingleConcatenatedFileAction");
1760       thread.setPriority(Thread.MIN_PRIORITY);
1761       thread.start();
1762     }
1763   }
1764 
1765   class CreateIndexAction1 extends AbstractAction {
1766     private static final long serialVersionUID = -3951091972912846869L;
1767 
1768     CreateIndexAction1() {
1769       super("Create Index");
1770       putValue(SHORT_DESCRIPTION, "Create index with documents from a corpus");
1771     }
1772 
1773     public void actionPerformed(ActionEvent e) {
1774       CreateIndexDialog cid = null;
1775       if(getWindow() instanceof Frame) {
1776         cid = new CreateIndexDialog((Frame)getWindow()(IndexedCorpus)target);
1777       }
1778       if(getWindow() instanceof Dialog) {
1779         cid = new CreateIndexDialog((Dialog)getWindow()(IndexedCorpus)target);
1780       }
1781       cid.setVisible(true);
1782     }
1783   }
1784 
1785   class CreateIndexAction extends AbstractAction {
1786     private static final long serialVersionUID = -292879296310753260L;
1787 
1788     CreateIndexAction() {
1789       super("Index Corpus");
1790       putValue(SHORT_DESCRIPTION, "Create index with documents from the corpus");
1791       createIndexGui = new CreateIndexGUI();
1792     }
1793 
1794     public void actionPerformed(ActionEvent e) {
1795       boolean ok = OkCancelDialog.showDialog(largeView, createIndexGui,
1796               "Index \"" + target.getName() "\" corpus");
1797       if(ok) {
1798         DefaultIndexDefinition did = new DefaultIndexDefinition();
1799         IREngine engine = createIndexGui.getIREngine();
1800         did.setIrEngineClassName(engine.getClass().getName());
1801 
1802         did.setIndexLocation(createIndexGui.getIndexLocation().toString());
1803 
1804         // add the content if wanted
1805         if(createIndexGui.getUseDocumentContent()) {
1806           did.addIndexField(new IndexField("body"new DocumentContentReader(),
1807                   false));
1808         }
1809         // add all the features
1810         Iterator featIter = createIndexGui.getFeaturesList().iterator();
1811         while(featIter.hasNext()) {
1812           String featureName = (String)featIter.next();
1813           did.addIndexField(new IndexField(featureName, new FeatureReader(
1814                   featureName)false));
1815         }
1816 
1817         ((IndexedCorpus)target).setIndexDefinition(did);
1818 
1819         Thread thread = new Thread(new Runnable() {
1820           public void run() {
1821             try {
1822               fireProgressChanged(1);
1823               fireStatusChanged("Indexing corpus...");
1824               long start = System.currentTimeMillis();
1825               ((IndexedCorpus)target).getIndexManager().deleteIndex();
1826               fireProgressChanged(10);
1827               ((IndexedCorpus)target).getIndexManager().createIndex();
1828               fireProgressChanged(100);
1829               fireProcessFinished();
1830               fireStatusChanged("Corpus indexed in "
1831                       + NumberFormat
1832                               .getInstance()
1833                               .format(
1834                                       (double)(System.currentTimeMillis() - start1000)
1835                       " seconds");
1836             }
1837             catch(IndexException ie) {
1838               JOptionPane.showMessageDialog(getLargeView() != null
1839                       ? getLargeView()
1840                       : getSmallView()"Could not create index!\n "
1841                       "See \"Messages\" tab for details!""GATE",
1842                       JOptionPane.ERROR_MESSAGE);
1843               ie.printStackTrace(Err.getPrintWriter());
1844             }
1845             finally {
1846               fireProcessFinished();
1847             }
1848           }
1849         });
1850         thread.setPriority(Thread.MIN_PRIORITY);
1851         thread.start();
1852       }
1853     }
1854 
1855     CreateIndexGUI createIndexGui;
1856   }
1857 
1858   class OptimizeIndexAction extends AbstractAction {
1859     private static final long serialVersionUID = 261845730081082766L;
1860 
1861     OptimizeIndexAction() {
1862       super("Optimize Index");
1863       putValue(SHORT_DESCRIPTION, "Optimize existing index");
1864     }
1865 
1866     public boolean isEnabled() {
1867       return ((IndexedCorpus)target).getIndexDefinition() != null;
1868     }
1869 
1870     public void actionPerformed(ActionEvent e) {
1871       Thread thread = new Thread(new Runnable() {
1872         public void run() {
1873           try {
1874             fireProgressChanged(1);
1875             fireStatusChanged("Optimising index...");
1876             long start = System.currentTimeMillis();
1877             ((IndexedCorpus)target).getIndexManager().optimizeIndex();
1878             fireStatusChanged("Index optimised in "
1879                     + NumberFormat
1880                             .getInstance()
1881                             .format(
1882                                     (double)(System.currentTimeMillis() - start1000)
1883                     " seconds");
1884             fireProcessFinished();
1885           }
1886           catch(IndexException ie) {
1887             JOptionPane.showMessageDialog(getLargeView() != null
1888                     ? getLargeView()
1889                     : getSmallView()"Errors during optimisation!""GATE",
1890                     JOptionPane.PLAIN_MESSAGE);
1891             ie.printStackTrace(Err.getPrintWriter());
1892           }
1893           finally {
1894             fireProcessFinished();
1895           }
1896         }
1897       });
1898       thread.setPriority(Thread.MIN_PRIORITY);
1899       thread.start();
1900     }
1901   }
1902 
1903   class DeleteIndexAction extends AbstractAction {
1904     private static final long serialVersionUID = 6121632107964572415L;
1905 
1906     DeleteIndexAction() {
1907       super("Delete Index");
1908       putValue(SHORT_DESCRIPTION, "Delete existing index");
1909     }
1910 
1911     public boolean isEnabled() {
1912       return ((IndexedCorpus)target).getIndexDefinition() != null;
1913     }
1914 
1915     public void actionPerformed(ActionEvent e) {
1916       int answer = JOptionPane.showOptionDialog(getLargeView() != null
1917               ? getLargeView()
1918               : getSmallView()"Do you want to delete index?""Gate",
1919               JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
1920               null, null);
1921       if(answer == JOptionPane.YES_OPTION) {
1922         try {
1923           IndexedCorpus ic = (IndexedCorpus)target;
1924           if(ic.getIndexManager() != null) {
1925             ic.getIndexManager().deleteIndex();
1926             ic.getFeatures().remove(
1927                     GateConstants.CORPUS_INDEX_DEFINITION_FEATURE_KEY);
1928           }
1929           else {
1930             JOptionPane.showMessageDialog(getLargeView() != null
1931                     ? getLargeView()
1932                     : getSmallView()"There is no index to delete!""GATE",
1933                     JOptionPane.PLAIN_MESSAGE);
1934           }
1935         }
1936         catch(gate.creole.ir.IndexException ie) {
1937           ie.printStackTrace();
1938         }
1939       }
1940     }
1941   }
1942 
1943   class CreateCorpusForDocAction extends AbstractAction {
1944     /**
1945      
1946      */
1947     private static final long serialVersionUID = -3698451324578510407L;
1948 
1949     public CreateCorpusForDocAction() {
1950       super("New Corpus with this Document");
1951     }
1952 
1953     public void actionPerformed(ActionEvent e) {
1954       try {
1955         Corpus corpus = Factory.newCorpus("Corpus for " + target.getName());
1956         corpus.add(target);
1957       }
1958       catch(ResourceInstantiationException rie) {
1959         Err.println("Exception creating corpus");
1960         rie.printStackTrace(Err.getPrintWriter());
1961       }
1962     }
1963   }
1964 
1965   public void removeViews() {
1966     // delete all the VRs that were created
1967     if(largeView != null) {
1968       if(largeView instanceof VisualResource) {
1969         // we only had a view so no tabbed pane was used
1970         if(largeView instanceof ActionsPublisher)
1971           actionPublishers.remove(largeView);
1972         Factory.deleteResource((VisualResource)largeView);
1973       }
1974       else {
1975         Component vrs[] ((JTabbedPane)largeView).getComponents();
1976         for(int i = 0; i < vrs.length; i++) {
1977           if(vrs[iinstanceof VisualResource) {
1978             if(vrs[iinstanceof ActionsPublisher)
1979               actionPublishers.remove(vrs[i]);
1980             Factory.deleteResource((VisualResource)vrs[i]);
1981           }
1982         }
1983       }
1984       largeView = null;
1985     }
1986 
1987     if(smallView != null) {
1988       if(smallView instanceof VisualResource) {
1989         // we only had a view so no tabbed pane was used
1990         if(smallView instanceof ActionsPublisher)
1991           actionPublishers.remove(smallView);
1992         Factory.deleteResource((VisualResource)smallView);
1993       }
1994       else {
1995         Component vrs[] ((JTabbedPane)smallView).getComponents();
1996         for(int i = 0; i < vrs.length; i++) {
1997           if(vrs[iinstanceof VisualResource) {
1998             if(vrs[iinstanceof ActionsPublisher)
1999               actionPublishers.remove(vrs[i]);
2000             Factory.deleteResource((VisualResource)vrs[i]);
2001           }
2002         }
2003       }
2004       smallView = null;
2005     }
2006     viewsBuilt = false;
2007   }
2008 
2009   /**
2010    * Releases the memory, removes the listeners, cleans up. Will get
2011    * called when the target resource is unloaded from the system
2012    */
2013   public void cleanup() {
2014 
2015     removeViews();
2016     Gate.getCreoleRegister().removeCreoleListener(this);
2017     target = null;
2018   }
2019 
2020   class ProxyStatusListener implements StatusListener {
2021     public void statusChanged(String text) {
2022       fireStatusChanged(text);
2023     }
2024   }
2025 
2026   protected void fireProgressChanged(int e) {
2027     if(progressListeners != null) {
2028       Vector listeners = progressListeners;
2029       int count = listeners.size();
2030       for(int i = 0; i < count; i++) {
2031         ((ProgressListener)listeners.elementAt(i)).progressChanged(e);
2032       }
2033     }
2034   }// protected void fireProgressChanged(int e)
2035 
2036   protected void fireProcessFinished() {
2037     if(progressListeners != null) {
2038       Vector listeners = progressListeners;
2039       int count = listeners.size();
2040       for(int i = 0; i < count; i++) {
2041         ((ProgressListener)listeners.elementAt(i)).processFinished();
2042       }
2043     }
2044   }// protected void fireProcessFinished()
2045 
2046   @SuppressWarnings("unchecked")
2047   public synchronized void removeStatusListener(StatusListener l) {
2048     if(statusListeners != null && statusListeners.contains(l)) {
2049       Vector<StatusListener> v = (Vector<StatusListener>)statusListeners
2050               .clone();
2051       v.removeElement(l);
2052       statusListeners = v;
2053     }
2054   }// public synchronized void removeStatusListener(StatusListener l)
2055 
2056   @SuppressWarnings("unchecked")
2057   public synchronized void addStatusListener(StatusListener l) {
2058     Vector<StatusListener> v = statusListeners == null
2059             new Vector<StatusListener>(2)
2060             (Vector<StatusListener>)statusListeners.clone();
2061     if(!v.contains(l)) {
2062       v.addElement(l);
2063       statusListeners = v;
2064     }
2065   }// public synchronized void addStatusListener(StatusListener l)
2066 
2067   protected void fireStatusChanged(String e) {
2068     if(statusListeners != null) {
2069       Vector listeners = statusListeners;
2070       int count = listeners.size();
2071       for(int i = 0; i < count; i++) {
2072         ((StatusListener)listeners.elementAt(i)).statusChanged(e);
2073       }
2074     }
2075   }
2076 
2077   public void statusChanged(String e) {
2078     fireStatusChanged(e);
2079   }
2080 
2081   public void progressChanged(int e) {
2082     fireProgressChanged(e);
2083   }
2084 
2085   public void processFinished() {
2086     fireProcessFinished();
2087   }
2088 
2089   public Window getWindow() {
2090     return window;
2091   }
2092 
2093   public void resourceLoaded(CreoleEvent e) {
2094   }
2095 
2096   public void resourceUnloaded(CreoleEvent e) {
2097   }
2098 
2099   public void resourceRenamed(Resource resource, String oldName, String newName) {
2100   }
2101 
2102   public void datastoreOpened(CreoleEvent e) {
2103   }
2104 
2105   public void datastoreCreated(CreoleEvent e) {
2106   }
2107 
2108   public void datastoreClosed(CreoleEvent e) {
2109     if(getTarget() == e.getDatastore()) cleanup();
2110   }
2111 }// class DefaultResourceHandle